From: Ramon G. F. <ra...@pd...> - 2004-02-27 04:21:55
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Thu Feb 26 2004 20:19:38 PST Log message: Placing workfiles of rtp under gst-sandbox. Added files: rtpdec : gstrtpdec.c gstrtpdec.h gstrtphandler.h rtp_ctl_event.h rtp_packet.h Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtphandler.h?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_ctl_event.h?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_packet.h?rev=1.1&content-type=text/vnd.viewcvs-markup ====Begin Diffs==== --- NEW FILE: gstrtpdec.c --- /* Copyright (c) 2003 Ramon Garcia Fernandez Sponsored by CSOA Laboratorio 3 http://laboratorio3.net Based on the template code copyright (C) 1999 Erik Walthinsen <om...@cs...> */ #include <gst/gst.h> #include <gst/gstevent.h> #include <glib/gmem.h> #include <glib/gmain.h> #include <sys/time.h> #include <time.h> #include <sys/poll.h> #include <stdlib.h> #include <assert.h> #include "gstrtpdec.h" static GstElementDetails rtpdec_details = { "Rtpdec", "Source/Rtpdec", "LGPL", "Rtp decoder", "0.0", "Ramon Garcia Fernandez. " "Sponsored by CSOA Laboratorio 3 http://laboratorio3.net", "(C) 2002, 2003" }; /* Filter signals and args */ enum { /* FILL ME */ LAST_SIGNAL ARG_0, GST_PAD_TEMPLATE_FACTORY (gst_rtpdec_sink_factory, "sink", GST_PAD_SRC, GST_PAD_ALWAYS, NULL /* no caps */ ); GST_PAD_TEMPLATE_FACTORY (gst_rtpdec_src_factory, "src_%d", static void gst_rtpdec_class_init (GstRtpdecClass *klass); static GHashTable* gst_rtpdec_create_av_mapping(); static void gst_rtpdec_init (GstRtpdec *filter); static void gst_rtpdec_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void gst_rtpdec_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void gst_rtpdec_chain(GstPad* pad, GstBuffer* buffer); static void gst_rtpdec_handle_control_packet(GstRtpdec* element, char* data, int data_size); static void gst_rtpdec_handle_rtcp_sender_report(GstRtpdec* element, struct rtcp_sender_report* packet); static void gst_rtpdec_handle_rtcp_recv_report(GstRtpdec* element, struct rtcp_recv_report* packet); static void gst_rtpdec_handle_recv_block(GstRtpdec* element, struct reception_block* packet); static void gst_rtpdec_handle_rtcp_sdes(GstRtpdec* element, struct rtcp_sdes* packet); static void gst_rtpdec_handle_rtcp_bye(GstRtpdec* element, struct rtcp_bye* packet); static void gst_rtpdec_handle_rtcp_app(GstRtpdec* element, struct rtcp_app* packet); static unsigned int gst_rtpdec_rtcp_section_size(struct rtcp_common_header* packet); static void gst_rtpdec_handle_data_packet(GstRtpdec* element, GstBuffer* buffer); static gboolean gst_rtpdec_change_payload_type(GstRtpdec* element, struct sender_info* sender_info, gchar payload_type); static struct sender_info* gst_rtpdec_get_sender_info(GstRtpdec* element, guint32 identifier, gboolean create_if_new); static void gst_rtpdec_remove_sender(GstRtpdec* element, guint32 identifier); static struct recv_info* gst_rtpdec_get_recv_info(GstRtpdec* element, guint32 identifier); static void gst_rtpdec_set_recv_info_item_cname(struct recv_info* recv_info, gchar* text, unsigned int length); static void gst_rtpdec_set_recv_info_item_name(struct recv_info* recv_info, gchar* text, unsigned int length); static void gst_rtpdec_set_recv_info_item_email(struct recv_info* recv_info, gchar* text, unsigned int length); static void gst_rtpdec_remove_receiver(GstRtpdec* element, guint32 identifier); static void gst_rtpdec_set_clock(GstElement* element, GstClock* clock); /* End of declarations */ static GstElementClass *parent_class = NULL; typedef enum { GST_RTPDEC_CONTROL = 100 } GstRtpEventType; GType gst_rtpdec_get_type (void) { static GType rtpdec_type = 0; if (!rtpdec_type) { static const GTypeInfo rtpdec_info = { sizeof (GstRtpdecClass), NULL, (GClassInitFunc) gst_rtpdec_class_init, sizeof (GstRtpdec), 0, (GInstanceInitFunc) gst_rtpdec_init, }; rtpdec_type = g_type_register_static (GST_TYPE_ELEMENT, "GstRtpdec", &rtpdec_info, 0); } return rtpdec_type; } /* initialize the rtpdec's class */ static void gst_rtpdec_class_init (GstRtpdecClass *klass) GObjectClass *gobject_class; GstElementClass *gstelement_class; GstRtpdecClass *gst_rtpdec_class; gobject_class = (GObjectClass*) klass; gstelement_class = (GstElementClass*) klass; gst_rtpdec_class = (GstRtpdecClass*) klass; parent_class = g_type_class_ref (GST_TYPE_ELEMENT); gobject_class->set_property = gst_rtpdec_set_property; gobject_class->get_property = gst_rtpdec_get_property; gstelement_class->set_clock = gst_rtpdec_set_clock; gst_rtpdec_class->default_mapping = gst_rtpdec_create_av_mapping(); static GHashTable* gst_rtpdec_create_av_mapping() GHashTable* result; struct fixed_payload { int number; const char* name; int sample_rate; int num_channels; }; struct fixed_payload fixed_payloads[] = { {.number = 0, .name = "audio/pcmu", .sample_rate = 8000, .num_channels = 1}, {.number = 3, .name = "audio/gsm", .sample_rate = 8000, .num_channels = 1}, {.number = 4, .name = "audio/g723", .sample_rate = 8000, .num_channels = 1}, {.number = 5, .name = "audio/dvi4", .sample_rate = 8000, .num_channels = 1}, {.number = 6, .name = "audio/dvi4", .sample_rate = 16000,.num_channels = 1}, {.number = 7, .name = "audio/lpc", .sample_rate = 8000, .num_channels = 1}, {.number = 8, .name = "audio/pcma", .sample_rate = 8000, .num_channels = 1}, {.number = 9, .name = "audio/g722", .sample_rate = 8000, .num_channels = 1}, {.number =10, .name = "audio/l16", .sample_rate = 44100,.num_channels = 2}, {.number =11, .name = "audio/l16", .sample_rate = 44100,.num_channels = 1} unsigned int i; result = g_hash_table_new(g_int_hash, g_int_equal); for (i = 0; i < sizeof(fixed_payloads)/sizeof(struct fixed_payload); i++) { int* number; struct payload_desc* payload_desc = g_new(struct payload_desc, 1); int* sample_rate; int* num_channels; payload_desc->properties = g_hash_table_new(g_str_hash, g_str_equal); sample_rate = g_new(int, 1); *sample_rate = fixed_payloads[i].sample_rate ; g_hash_table_insert(payload_desc->properties, (gpointer) "sample-rate", (gpointer) sample_rate); num_channels = g_new(int, 1); *num_channels = fixed_payloads[i].num_channels; g_hash_table_insert(payload_desc->properties, (gpointer) "channels", (gpointer) num_channels); g_hash_table_insert(payload_desc->properties, (gpointer) "name", (gpointer) fixed_payloads[i].name); number = g_new(int, 1); *number = 0; g_hash_table_insert(result, (gpointer) number, (gpointer) payload_desc); return result; gst_rtpdec_init (GstRtpdec *element) element->sinkpad = gst_pad_new_from_template (gst_rtpdec_src_factory (), "sink"); gst_element_add_pad (GST_ELEMENT (element), element->sinkpad); gst_pad_set_chain_function(element->sinkpad, gst_rtpdec_chain); element->clock = NULL; gst_rtpdec_chain(GstPad* pad, GstBuffer* buffer) GstRtpdec* element; element = GST_RTPDEC(GST_OBJECT_PARENT(pad)); g_return_if_fail (element != NULL); g_return_if_fail (GST_IS_RTPDEC (element)); if (GST_IS_EVENT(buffer)) { GstEvent* event = GST_EVENT(buffer); if (event->type == GST_RTPDEC_CONTROL) { struct rtp_ctl_event_data* ctl_data = (struct rtp_ctl_event_data*) &event->event_data; gst_rtpdec_handle_control_packet(element, ctl_data->data, ctl_data->size); gst_event_unref(event); } else { gst_pad_event_default(pad, event); } } else { gst_rtpdec_handle_data_packet(element, buffer); static void gst_rtpdec_handle_control_packet(GstRtpdec* element, char* data, int data_size) while(1) { char* current_packet = data; unsigned int remaining_data = data_size; struct rtcp_common_header* header; unsigned int section_size; if (remaining_data < sizeof(struct rtcp_common_header)) { /* Corrupted packet */ break; header = (struct rtcp_common_header*) current_packet; section_size = (ntohs(header->length) + 1)*4; if (section_size > remaining_data) { switch (header->packet_type) { case SENDER_REPORT: gst_rtpdec_handle_rtcp_sender_report(element, (struct rtcp_sender_report*) current_packet); case RECEIVER_REPORT: gst_rtpdec_handle_rtcp_recv_report(element, (struct rtcp_recv_report*) current_packet); case SOURCE_DESCRIPTION: gst_rtpdec_handle_rtcp_sdes(element, (struct rtcp_sdes*) current_packet); case BYE: gst_rtpdec_handle_rtcp_bye(element, (struct rtcp_bye*) current_packet); case APP: gst_rtpdec_handle_rtcp_app(element, (struct rtcp_app*) current_packet); if (section_size >= remaining_data) { current_packet += section_size; data_size -= section_size; g_free(data); gst_rtpdec_handle_rtcp_sender_report(GstRtpdec* element, struct rtcp_sender_report* packet) guint32 sync_src; guint32 packet_size; struct sender_info* sender_info; int num_recv; packet_size = gst_rtpdec_rtcp_section_size(&packet->common); if (packet_size < sizeof(struct rtcp_sender_report) + (packet->common.num_sources - 1)*sizeof(struct reception_block)) { return; sync_src = ntohl(packet->sync_src_rtcp_sender); sender_info = gst_rtpdec_get_sender_info(element, sync_src, TRUE); sender_info->received_srvctl = TRUE; sender_info->last_ctl_ntptime.integer = ntohl(packet->ntp_timestamp.integer); sender_info->last_ctl_ntptime.frac = ntohl(packet->ntp_timestamp.frac); sender_info->last_ctl_rtptimestamp = ntohl(packet->rtp_timestamp); sender_info->total_packets_received = ntohl(packet->num_packets_sent); gst_rtpdec_get_recv_info(element, sync_src); for (num_recv = 0; num_recv <= packet->common.num_sources; num_recv++) { gst_rtpdec_handle_recv_block(element, &packet->reception_blocks[num_recv]); gst_rtpdec_handle_rtcp_recv_report(GstRtpdec* element, struct rtcp_recv_report* packet) unsigned int packet_size; if (packet_size < sizeof(struct rtcp_recv_report) + (packet->common.num_sources - 1)*sizeof(struct rtcp_recv_report)) { gst_rtpdec_handle_recv_block(GstRtpdec* element, struct reception_block* block) struct recv_info* foo; foo = gst_rtpdec_get_recv_info(element, ntohl(block->identifier)); gst_rtpdec_handle_rtcp_sdes(GstRtpdec* element, struct rtcp_sdes* packet) struct sdes_chunk* this_chunk; unsigned int num_chunks; unsigned int total_size, remaining_size; num_chunks = packet->common.num_sources; total_size = gst_rtpdec_rtcp_section_size(&packet->common) - sizeof(packet->common); this_chunk = &packet->chunks[0]; remaining_size = total_size; unsigned int item_remaining_size; unsigned int this_chunk_size; guint32 contrib_src; struct recv_info* recv_info; struct sdes_item* this_item; if (remaining_size < (sizeof(struct sdes_chunk) - sizeof(struct sdes_item) + 1)) { // FIXME: log invalid packet (source IP, ...) contrib_src = ntohl(this_chunk->identifier); recv_info = gst_rtpdec_get_recv_info(element, contrib_src); item_remaining_size = remaining_size - sizeof(this_chunk->identifier); this_chunk_size = remaining_size + sizeof(this_chunk->identifier); this_item = &this_chunk->items[0]; while(1) { unsigned int this_item_size; if (this_item->type == END){ break; } /* Ensure that item->length is readable */ if (item_remaining_size < sizeof(struct sdes_item) - sizeof(this_item->text)){ this_item_size = sizeof(struct sdes_item) + sizeof(this_item->text)* (this_item->length - 1); if (item_remaining_size < this_item_size) { switch(this_item->type) { case CNAME: gst_rtpdec_set_recv_info_item_cname(recv_info, &this_item->text[0], this_item->length); case NAME: gst_rtpdec_set_recv_info_item_name(recv_info, &this_item->text[0], this_item->length); case EMAIL: gst_rtpdec_set_recv_info_item_email(recv_info, &this_item->text[0], this_item->length); default: this_chunk_size += this_item_size; item_remaining_size -= this_item_size; this_item = (struct sdes_item*) ((char*) this_item + this_item_size); if (item_remaining_size <= 1) { /* Round up to a multiple of 4*/ this_chunk_size = (this_chunk_size + 3) % 4; remaining_size -= this_chunk_size; if (remaining_size == 0) { this_chunk = (struct sdes_chunk*) ( (char*) this_chunk + this_chunk_size); gst_rtpdec_handle_rtcp_bye(GstRtpdec* element, struct rtcp_bye* packet) unsigned int num_srcs, total_size; total_size = gst_rtpdec_rtcp_section_size(&packet->common); num_srcs = packet->common.num_sources; if (total_size < sizeof(*packet) + sizeof(packet->identifier[0])*(num_srcs - 1)) { /* Invalid packet */ for (i = 0; i < num_srcs; i++) { guint32 id; id = ntohl(packet->identifier[i]); gst_rtpdec_remove_sender(element, id); gst_rtpdec_remove_receiver(element, id); gst_rtpdec_handle_rtcp_app(GstRtpdec* element, struct rtcp_app* packet) guint32 identifier; if (packet_size < sizeof(*packet) - sizeof(packet->data)) { identifier = packet->identifier; sender_info = gst_rtpdec_get_sender_info(element, identifier, FALSE); gst_rtpdec_get_recv_info(element, identifier); if (sender_info == NULL) { if (sender_info->handler) { gst_irtpdec_handler_get_app_packet(sender_info->handler, ntohl(packet->name), packet->data, packet_size - sizeof(*packet) + sizeof(packet->data)); static unsigned int gst_rtpdec_rtcp_section_size(struct rtcp_common_header* packet) unsigned int length; length = (ntohs(packet->length) + 1)*4; if (packet->padding == 1) { length = ntohl(* (guint32*) ((char*) packet + length - sizeof(guint32))); return length; gst_rtpdec_handle_data_packet(GstRtpdec* element, GstBuffer* buffer) struct rtp_packet* packet; unsigned int payload_offset; GstClockTime now; guint32 this_data_timestamp; GstClockTime buffer_timestamp; if (GST_BUFFER_SIZE(buffer) < sizeof(struct rtp_packet)) { packet = (struct rtp_packet*) GST_BUFFER_DATA(buffer); packet_size = GST_BUFFER_SIZE(buffer); packet_size = ntohl(*(guint32 *)( (char*) packet + packet_size - sizeof(guint32))); payload_offset = sizeof(struct rtp_packet) + (packet->num_contrib_sources - 1)*sizeof(unsigned long); if (packet_size < payload_offset) { if (packet->extension) { struct rtp_packet_extension* extension = (struct rtp_packet_extension*) ((char*) packet + packet->extension); packet_size += sizeof(struct rtp_packet_extension) + ntohs(extension->length); identifier = ntohl(packet->identifier); sender_info = gst_rtpdec_get_sender_info(element, identifier, TRUE); /* Update statistics */ sender_info->total_packets_received++; /* FIXME: byte count should include IP headers */ sender_info->total_bytes_received += GST_BUFFER_SIZE(buffer); sender_info->bytes_received += GST_BUFFER_SIZE(buffer); sender_info->packets_received++; if (sender_info->received_data) { guint16 num_packets_lost; /* Be careful with cycling numbers */ num_packets_lost = ntohs(packet->sequence_number) - sender_info->last_sequence_number - (guint16) 1; sender_info->total_packets_lost += num_packets_lost; sender_info->packets_lost += num_packets_lost; now = gst_clock_get_time(element->clock); this_data_timestamp = ntohl(packet->timestamp); GstClockTimeDiff time_diff; guint32 new_diff; time_diff = now - sender_info->time_last_data_packet_received; if (sender_info->sample_rate != 0) { new_diff = abs(time_diff*sender_info->sample_rate/GST_SECOND - (this_data_timestamp - sender_info->last_data_timestamp)); new_diff = 0; sender_info->jitter = sender_info->jitter + (new_diff - sender_info->jitter)/16; sender_info->last_data_timestamp = this_data_timestamp; sender_info->time_last_data_packet_received = now; sender_info->received_data = TRUE; sender_info->last_sequence_number = ntohs(packet->sequence_number); if (!sender_info->received_srvctl) { /* FIXME: For now we ignore data packets if we didn't receive a control packet because then we cannot know the correct timestamp. Perhaps there should be a better policy */ if (sender_info->output == NULL) { sender_info->output = gst_pad_new_from_template(GST_PAD_TEMPLATE_GET(gst_rtpdec_src_factory), g_strdup_printf("src_%d", identifier)); gst_element_add_pad(GST_ELEMENT(element), sender_info->output); if (sender_info->payload_type != packet->payload_type) { if (!gst_rtpdec_change_payload_type(element, sender_info, packet->payload_type)) { /* We do not know how to handle this payload type. Exit */ return; assert(sender_info->handler != NULL); if (sender_info->sample_rate == 0) { sender_info->sample_rate = gst_irtpdec_handler_get_sample_rate(sender_info->handler, buffer, payload_offset); if (sender_info->sample_rate == 0) { /* Unknown sample rate */ /* FIXME: Handle years larger than 2038. Interpret ntptime according to the current year */ buffer_timestamp = ((guint64) this_data_timestamp - sender_info->last_ctl_rtptimestamp)*GST_SECOND/sender_info->sample_rate + ((guint64) sender_info->last_ctl_ntptime.integer)*GST_SECOND + (((guint64) sender_info->last_ctl_ntptime.frac)*GST_SECOND << 32) ; gst_irtpdec_handler_get_data_packet(sender_info->handler, buffer, payload_offset, buffer_timestamp); static gboolean gst_rtpdec_change_payload_type(GstRtpdec* element, struct sender_info* sender_info, gchar payload_type) struct payload_desc* payload_desc; payload_desc = NULL; if (element->mapping) { payload_desc = (struct payload_desc*) g_hash_table_lookup(element->mapping, (gconstpointer) &payload_type); if (payload_desc == NULL) { payload_desc = (struct payload_desc*) g_hash_table_lookup(GST_RTPDEC_GET_CLASS(element)->default_mapping, (gconstpointer) &payload_type); return FALSE; /* Set sample rate */ unsigned int* sample_rate_ptr; sample_rate_ptr = (unsigned int*) g_hash_table_lookup(payload_desc->properties, "sample-rate"); if (sample_rate_ptr == NULL) { /* A bad entry for this payload type. It should have that property */ return FALSE; sender_info->sample_rate = *sample_rate_ptr; /* Create the new element */ GstElement* handler_element; GString* handler_name; handler_name = g_string_sized_new(20); g_string_append_len(handler_name, "rtp-", sizeof("rtp-")); g_string_append(handler_name, payload_desc->mime_type); handler_element = gst_element_factory_make(handler_name->str, NULL); if (handler_element == NULL || GST_IS_IRTPDEC_HANDLER(handler_element)) { /* Could not find a handler for this type */ g_string_free(handler_name, TRUE); if (handler_element != NULL) { gst_object_unref(GST_OBJECT(handler_element)); if (sender_info->handler_element) { gst_object_unref(GST_OBJECT(sender_info->handler_element)); sender_info->handler_element = NULL; sender_info->handler = NULL; sender_info->handler_element = handler_element; sender_info->handler = GST_IRTPDEC_HANDLER(handler_element); GstCaps* caps = gst_caps_new("rtpdec-out", payload_desc->mime_type, gst_props_empty_new()); gst_irtpdec_set_caps_properties(caps, payload_desc->properties); gst_pad_try_set_caps(sender_info->output, caps); return TRUE; static struct sender_info* gst_rtpdec_get_sender_info(GstRtpdec* element, guint32 id, gboolean create_if_new) struct sender_info* result; result = (struct sender_info *) g_hash_table_lookup(element->sender_list, (gconstpointer)&id); if (result == NULL) { if (create_if_new) { guint32* ptr_id = g_new(guint32, 1); *ptr_id = id; result = g_new(struct sender_info, 1); result->magic = sender_magic; result->received_srvctl = FALSE; result->received_data = FALSE; result->total_packets_received = 0; result->total_packets_sent = 0; result->total_packets_lost = 0; result->total_bytes_received = 0; result->jitter = 0.0; result->packets_received = 0.0; result->packets_lost = 0; result->bytes_received = 0; result->last_ctl_ntptime = (struct ntptime) {0, 0}; result->last_ctl_rtptimestamp = 0; result->output = NULL; result->sample_rate = 0; result->payload_type = 0; result->handler = NULL; result->handler_element = NULL; g_hash_table_insert(element->sender_list, (gpointer) ptr_id, (gpointer) result); assert(result->magic == sender_magic); gst_rtpdec_remove_sender(GstRtpdec* element, guint32 identifier) guint32* stored_identifier; gboolean found; gpointer stored_identifier_gptr; gpointer sender_info_gptr; found = g_hash_table_lookup_extended(element->sender_list, (gconstpointer) &identifier, &stored_identifier_gptr, &sender_info_gptr); stored_identifier = (guint32 *) stored_identifier_gptr; sender_info = (struct sender_info*) sender_info_gptr; if (found) { if (sender_info->output != NULL) { GstPad* peer; peer = GST_PAD_PEER(sender_info->output); if (peer) { gst_pad_unlink(sender_info->output, peer); gst_element_remove_pad(GST_ELEMENT(element), sender_info->output); gst_object_unref(GST_OBJECT(sender_info->output)); gst_object_unref(GST_OBJECT(sender_info->handler)); g_free(sender_info); g_free(stored_identifier); g_hash_table_remove(element->sender_list, (gconstpointer) &identifier); static struct recv_info* gst_rtpdec_get_recv_info(GstRtpdec* element, guint32 identifier) struct recv_info* result; result = (struct recv_info*) g_hash_table_lookup(element->recv_list, (gconstpointer) &identifier); struct recv_info* result = g_new(struct recv_info, 1); result->magic = recv_magic; result->cname = NULL; result->name = NULL; result->email = NULL; assert(result->magic == recv_magic); gst_rtpdec_remove_receiver(GstRtpdec* element, guint32 identifier) gpointer result_gptr; found = g_hash_table_lookup_extended(element->recv_list, (gconstpointer) &identifier, &stored_identifier_gptr, &result_gptr); stored_identifier = (guint32*) stored_identifier_gptr; result = (struct recv_info*) result_gptr; assert(result != NULL); if (result->cname != NULL) { g_string_free(result->cname, TRUE); if (result->name != NULL) { g_string_free(result->name, TRUE); if (result->email != NULL) { g_string_free(result->email, TRUE); gst_rtpdec_set_recv_info_item_cname(struct recv_info* recv_info, gchar* text, unsigned int length) if (recv_info->cname != NULL) { g_string_free(recv_info->cname, TRUE); recv_info->cname = g_string_new_len(text, length); gst_rtpdec_set_recv_info_item_name(struct recv_info* recv_info, gchar* text, unsigned int length) if (recv_info->name != NULL) { g_string_free(recv_info->name, TRUE); recv_info->name = g_string_new_len(text, length); gst_rtpdec_set_recv_info_item_email(struct recv_info* recv_info, gchar* text, unsigned int length) if (recv_info->email != NULL) { g_string_free(recv_info->email, TRUE); recv_info->email = g_string_new_len(text, length); gst_rtpdec_set_clock(GstElement* element, GstClock* clock) GST_RTPDEC(element)->clock = clock; gst_rtpdec_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) GstRtpdec *filter; g_return_if_fail (GST_IS_RTPDEC (object)); filter = GST_RTPDEC (object); switch (prop_id) default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; gst_rtpdec_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) switch (prop_id) { /* entry point to initialize the plug-in * initialize the plug-in itself * register the element factories and pad templates * register the features */ rtpdec_init (GModule *module, GstPlugin *plugin) GstElementFactory *factory; factory = gst_element_factory_new ("rtpdec", GST_RTPDEC_TYPE, &rtpdec_details); g_return_val_if_fail (factory != NULL, FALSE); gst_element_factory_add_pad_template (factory, gst_rtpdec_src_factory ()); gst_rtpdec_sink_factory ()); gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); /* plugin initialisation succeeded */ /* this is the structure that gst-register looks for * so keep the name plugin_desc, or you cannot get your plug-in registered */ GstPluginDesc plugin_desc = { GST_VERSION_MAJOR, GST_VERSION_MINOR, "rtpdec", rtpdec_init --- NEW FILE: gstrtpdec.h --- #ifndef __GST_RTPDEC_H__ #define __GST_RTPDEC_H__ #include <netinet/in.h> #include <glib/gtypes.h> #include <glib/ghash.h> #include <glib/gstring.h> #include "rtp_packet.h" #include "rtp_ctl_event.h" #include "gstrtphandler.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* #define's don't like whitespacey bits */ #define GST_RTPDEC_TYPE \ (gst_rtpdec_get_type()) #define GST_RTPDEC(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_RTPDEC_TYPE,GstRtpdec)) #define GST_RTPDEC_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass),GST_RTPDEC_TYPE,GstRtpdec)) #define GST_IS_RTPDEC(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_RTPDEC_TYPE)) #define GST_IS_RTPDEC_CLASS(obj) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTPDEC)) #define GST_RTPDEC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_RTPDEC_TYPE, GstRtpdecClass)) typedef struct _GstRtpdec GstRtpdec; typedef struct _GstRtpdecClass GstRtpdecClass; const guint32 sender_magic = 0x0c0deb12; const guint32 recv_magic = 0x0badbeef; struct _GstRtpdecHandler; typedef struct _GstRtpdecHandler GstRtpdecHandler; void gst_rtpdec_handler_get_data_packet(GstRtpdecHandler* handler, GstBuffer* buffer, unsigned int data_offset); void gst_rtpdec_handler_get_app_packet(GstRtpdecHandler* handler, guint32 type, gconstpointer data, unsigned int data_size); struct payload_desc { gchar* mime_type; GHashTable* properties; struct sender_info { guint32 magic; gboolean received_data; gboolean received_srvctl; unsigned int total_packets_received; /* According to us */ unsigned int total_packets_sent; /* According to the server, in last sender report */ unsigned int total_packets_lost; guint16 last_sequence_number; unsigned int total_bytes_received; guint32 jitter; /* Bellow are numbers since last control packet sent */ unsigned int packets_received; unsigned int packets_lost; unsigned int bytes_received; /* From the latest control packet. Used for setting the time of the buffer */ struct ntptime last_ctl_ntptime; guint32 last_ctl_rtptimestamp; /* For jitter calculation */ guint32 last_data_timestamp; GstClockTime time_last_data_packet_received; GstPad* output; unsigned int sample_rate; /* 0 means undefined, should take from the stream */ unsigned int payload_type; GstElement* handler_element; GstIRtpdecHandler* handler; struct recv_info { GString* name; GString* cname; GString* email; struct _GstRtpdec GstElement element; GstPad* sinkpad; /* mapping of payload byte => payload_desc */ GHashTable* mapping; guint32 myid; float fraction_rtcp_traffic; float senders_rtcp_traffic; /* Mapping of identifier -> sender_info */ GHashTable* sender_list; /* Mapping of identifier -> recv_info */ GHashTable* recv_list; GstClock* clock; struct _GstRtpdecClass GstElementClass parent_class; GHashTable* default_mapping; GType gst_rtpdec_get_type (void); #endif /* __GST_RTPDEC_H__ */ --- NEW FILE: gstrtphandler.h --- #include <glib-object.h> #include <gst/gstpad.h> #include <gst/gstbuffer.h> #include <gst/gstcaps.h> struct _GstIRtpdecHandler; typedef struct _GstIRtpdecHandler GstIRtpdecHandler; #define GST_IRTPDEC_HANDLER_TYPE (gst_irtpdec_handler_get_type()) #define GST_IRTPDEC_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_IRTPDEC_HANDLER_TYPE, GstIRtpdecHandler)) #define GST_IRTPDEC_HANDLER_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), GST_IRTPDEC_HANDLER_TYPE, GstIRtpdecHandlerClass)) #define GST_IS_IRTPDEC_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_IRTPDEC_HANDLER_TYPE)) #define GST_IS_IRTPDEC_HANDLER_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), GST_IRTPDEC_HANDLER_TYPE)) #define GST_IRTPDEC_HANDLER_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_IRTPDEC_HANDLER_TYPE, GstIRtpdecHandlerClass)) typedef struct _GstIRtpdecHandlerClass { GTypeInterface parent; void (*init)(GstPad* output, GHashTable* metadata); void (*get_data_packet)(GstBuffer* buffer, unsigned int data_offset, GstClockTime timestamp); unsigned int (*get_sample_rate)(GstBuffer* buffer, unsigned int data_offset); void (*get_app_packet)(guint32 tag, gconstpointer data, unsigned int data_size); void (*set_caps_properties)(GstCaps* caps, GHashTable* properties); } GstIRtpdecHandlerClass; GType gst_irtpdec_handler_get_type(void); void gst_irtpdec_handler_init(GstIRtpdecHandler* this, GstPad* output, GHashTable* metadata); void gst_irtpdec_handler_get_data_packet(GstIRtpdecHandler* this, GstBuffer* buffer, unsigned int data_offset, GstClockTime timestamp); void gst_irtpdec_handler_get_app_packet(GstIRtpdecHandler* this, guint32 tag, gconstpointer data, unsigned int data_size); unsigned int gst_irtpdec_handler_get_sample_rate(GstIRtpdecHandler* this, GstBuffer* buffer, unsigned int data_offset); void gst_irtpdec_set_caps_properties(GstCaps* caps, GHashTable* properties); --- NEW FILE: rtp_ctl_event.h --- struct rtp_ctl_event_data { unsigned int size; char* data; --- NEW FILE: rtp_packet.h --- struct __attribute__((packed)) rtp_packet { unsigned int version:2; unsigned int padding:1; unsigned int extension:1; unsigned int num_contrib_sources: 4; unsigned int mark:1; unsigned int payload_type:7; unsigned int sequence_number:16; unsigned int timestamp:32; unsigned int identifier:32; unsigned int contrib_sources[1]; struct __attribute__((packed)) rtp_packet_extension { guint16 tag; guint16 length; struct __attribute__((packed)) rtcp_common_header { unsigned int num_sources:5; enum {SENDER_REPORT = 200, RECEIVER_REPORT = 201, SOURCE_DESCRIPTION = 202, BYE = 203, APP = 204} packet_type:8; unsigned int length: 16; struct __attribute__((packed)) reception_block { guint8 fraction_lost_last; unsigned int cumul_packets_lost: 24; guint32 highest_sequence_number; guint32 last_timestamp_seen; guint32 time_since_last_packet; struct __attribute__((packed)) ntptime { guint32 integer; guint32 frac; struct __attribute__((packed)) rtcp_sender_report { struct rtcp_common_header common; guint32 sync_src_rtcp_sender; struct ntptime ntp_timestamp; guint32 rtp_timestamp; guint32 num_packets_sent; guint32 num_bytes_sent; struct reception_block reception_blocks[1]; struct __attribute__((packed)) rtcp_recv_report { struct __attribute__((packed)) rtcp_sdes { struct __attribute__((packed)) sdes_chunk { guint32 identifier; /* sync source or contrib source */ struct __attribute__((packed)) sdes_item { enum {END = 0, CNAME=1, NAME=2, EMAIL=3, PHONE=4, STREET_ADDRESS=5, TOOL=6, NOTE=7, PRIV=8} type: 8; guint8 length; gchar text[1]; } items[1]; /* WARNING: Variable length struct. Do not use the array index for values other than 0*/ } chunks[1]; /* Idem here */ struct __attribute__((packed)) rtcp_bye { guint32 identifier[1]; struct __attribute__((packed)) rtcp_app { guint32 name; char data[1]; |
From: Ramon G. F. <ra...@pd...> - 2004-02-27 04:49:58
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Thu Feb 26 2004 20:47:40 PST Log message: The previous commit included the wrong files. Added address handling, not yet integrated. Modified files: rtpdec : gstrtpdec.c gstrtpdec.h Added files: rtpdec : address.c address.h ntohll.h Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/address.c?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/address.h?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c.diff?r1=1.1&r2=1.2 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h.diff?r1=1.1&r2=1.2 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/ntohll.h?rev=1.1&content-type=text/vnd.viewcvs-markup ====Begin Diffs==== --- NEW FILE: address.c --- #include "address.h" #include <netdb.h> static gpointer gst_address_copy(gpointer); static void gst_address_free(gpointer); static gpointer gst_address_list_copy(gpointer); static void gst_address_list_free(gpointer); static gpointer gst_addr_port_copy(gpointer); static void gst_addr_port_free(gpointer); static gpointer gst_addr_port_list_copy(gpointer); static void gst_addr_port_list_free(gpointer); static void resolve_name(const gchar* name, GstNumAddress* result); GType gst_address_get_type(void) { static GType address_type = 0; if (address_type == 0) { address_type = g_boxed_type_register_static("GstAddress", gst_address_copy, gst_address_free); } return address_type; } static gpointer gst_address_copy(gpointer src) { GstAddress* addr_src = (GstAddress*) src; GstAddress* addr_result; addr_result = g_new0(GstAddress, 1); *addr_result = *addr_src; if (addr_src->type == NAME) { addr_result->addr.name = g_strdup(addr_src->addr.name); return (gpointer) addr_result; static void gst_address_free(gpointer ptr) GstAddress* addr_ptr = (GstAddress*) ptr; if (addr_ptr->type == NAME) { g_free(addr_ptr->addr.name); g_free(ptr); gst_address_list_get_type(void) { static GType type = 0; if (type == 0) { type = g_boxed_type_register_static("GstAddressList", gst_address_list_copy, gst_address_list_free); return type; gst_address_list_copy(gpointer src) GList* src_list = (GList*) src; GList* dest_list = NULL; GList* list_node = src_list; while (list_node != NULL) { dest_list = g_list_append(dest_list, gst_address_copy(list_node->data)); list_node = g_list_next(list_node); return (gpointer) dest_list; gst_address_list_free(gpointer ptr) GList* ptr_list = (GList*) ptr; GList* list_node = ptr_list; gst_address_free(list_node->data); list_node = g_list_remove_link(list_node, list_node); static gpointer gst_addr_port_copy(gpointer src) GstAddrPort* addr_src = (GstAddrPort*) src; GstAddrPort* addr_result; addr_result = g_new0(GstAddrPort, 1); if (addr_src->addr.type == NAME) { addr_result->addr.addr.name = g_strdup(addr_src->addr.addr.name); static void gst_addr_port_free(gpointer ptr) GstAddrPort* addr_ptr = (GstAddrPort*) ptr; if (addr_ptr->addr.type == NAME) { g_free(addr_ptr->addr.addr.name); gst_addr_port_get_type(void) type = g_boxed_type_register_static("GstAddrPort", gst_addr_port_copy, gst_addr_port_free); GType gst_addr_port_list_get_type(void) type = g_boxed_type_register_static("GstAddrPortList", gst_addr_port_list_copy, gst_addr_port_list_free); gst_addr_port_list_copy(gpointer src) dest_list = g_list_append(dest_list, gst_addr_port_copy(list_node->data)); gst_addr_port_list_free(gpointer ptr) gst_addr_port_free(list_node->data); void resolve_address(const GstAddress* address, GstNumAddress* result) if (result->alternatives != NULL) { g_free(result->alternatives); result->num_alternatives = 0 result->alternatives = NULL; switch (address->type) { case IPV4: result->num_alternatives = 1; result->alternatives = g_new(struct in6_addr, 1); map_ipv4_to_ipv6(address->addr.ipv4_address, result->alternatives[0]); break; case IPV6: result->alternatives[0] = address->addr.ipv6_address; case NAME: resolve_name(address->addr.name, result); resolve_name(const gchar* name, GstNumAddress* result) int error; struct addrinfo* result; struct addrinfo* link; error = getaddrinfo(name, NULL, NULL, &result); if (error != 0) return; result->num_alternatives = 0; link = result; while(link != NULL) { if (link->ai_family == AF_INET || link->ai_family == AF_INET6) { result->num_alternatives++; } link = link->ai_next; result->alternatives = g_new0(struct in6_addr, result->num_alternatives); alternative = result->alternatives; if (link->ai_protocol == AF_INET || link->ai_family == AF_INET6) { *alternative = ((struct sockaddr_in6 *) link->ai_addr)->sin6_addr; alternative++; freeaddrinfo(result); gboolean try_bind(int socket, const GstNumAddress* address, int port) int i; struct in6_addr addr; g_assert(address->num_alternatives > 0); for (i = 0; i < address->num_alternatives; i++) { addr = address->alternatives[i]; addr.sin_port = port; error = bind(socket, &addr, sizeof(struct in6_addr)); if (error == 0) { break; return (error != 0); void try_send(int socket, GstNumAddressPort* remote, const char* data, guint size) struct sockaddr_in6 peer; guint i; gboolean sucess; peer.sin6_port = remote->port; peer.sin6_flowinfo = 0; peer.sin6_scope_id = 0; for (i = 0; i < remote->address.num_alternatives; i++) { peer.sin6_addr = remote->address.alternatives[i]; error = sendto(socket, data, size, 0, &peer, sizeof(sockaddr_in6)); sucess = error >= 0; if (sucess) --- NEW FILE: address.h --- #ifndef ADDRESS_H #define ADDRESS_H #include <glib-object.h> #include <netinet/in.h> struct _GstAddress { enum {IPV4, IPV6, NAME} type; union addr_fmt { struct in_addr ipv4_address; struct in6_addr ipv6_address; char* name; } addr; }; typedef struct _GstAddress GstAddress; struct _GstAddrPort { GstAddress addr; unsigned short port; typedef struct _GstAddrPort GstAddrPort; GType gst_address_get_type(); GType gst_peer_get_type(); GType gst_address_list_get_type(); GType gst_addr_port_list_get_type(); #define GST_TYPE_ADDRESS (gst_address_get_type()) #define GST_TYPE_ADDR_PORT (gst_addr_port_get_type()) #define GST_TYPE_ADDRESS_LIST (gst_address_list_get_type()) #define GST_TYPE_ADDR_PORT_LIST (gst_addr_port_list_get_type()) /* Represents the address of a single logical machine, that can be accesses throught any of these addresses. It is the result of a name resolution that returns a list of addresses */ struct _GstNumAddress { guint num_alternatives; struct in6_addr* alternatives; typedef struct _GstNumAddress GstNumAddress; /* Represents a list of addresses. For instance, a list of authorized machines */ struct _GstNumAddresses { GList* list; /* Actually, a GList of <GstNumAddress> */ typedef struct _GstNumAddresses GstNumAddresses; struct _GstNumAddressPort { GstNumAddress address; guint16 port; typedef struct _GstNumAddressPort GstNumAddressPort; struct _GstNumAddressesPorts { GList* list; /* GList of <GstNumAddressPort> */ typedef struct _GstNumAddressesPorts GstNumAddressesPorts; void resolve_address(const GstAddress* address, GstNumAddress* result); void resolve_addresses(const GList* addresses, /* GList of GstAddress */ GstNumAddresses* result); void resolve_addresses_ports(const GList* addresses, /* GList of GstAddrPort */ GstNumAddressesPorts* result); gboolean try_bind(int socket, const GstNumAddress* address, int port); void try_send(int socket, GstNumAddressPort* remote, const char* data, guint size); #endif Index: gstrtpdec.c =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- a/gstrtpdec.c 27 Feb 2004 04:19:26 -0000 1.1 +++ b/gstrtpdec.c 27 Feb 2004 04:47:28 -0000 1.2 @@ -36,24 +36,26 @@ enum { ARG_0, + ARG_LOCAL_DATA_PORT, + ARG_LOCAL_DATA_ADDR, + ARG_LOCAL_ADDR, + ARG_REMOTE_HOST, + ARG_REMOTE_DATA_PORT, + ARG_REMOTE_CONTROL_PORT, + ARG_MULTICAST_ADDR, + ARG_MEDIA_MIME_MAPPING, + ARG_BANDWIDTH }; -GST_PAD_TEMPLATE_FACTORY (gst_rtpdec_sink_factory, - "sink", - GST_PAD_SRC, - GST_PAD_ALWAYS, - NULL /* no caps */ -); - -GST_PAD_TEMPLATE_FACTORY (gst_rtpdec_src_factory, - "src_%d", +static GstStaticPadTemplate gst_rtpdec_src_template = +GST_STATIC_PAD_TEMPLATE( + "src_%02d", GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS_ANY); -static void gst_rtpdec_class_init (GstRtpdecClass *klass); +static void gst_rtpdec_class_init(GstRtpdecClass *klass); static GHashTable* gst_rtpdec_create_av_mapping(); static void gst_rtpdec_init (GstRtpdec *filter); @@ -62,6 +64,8 @@ static void gst_rtpdec_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); +static void gst_rtpdec_main_loop(GstElement* element); + static void gst_rtpdec_chain(GstPad* pad, GstBuffer* buffer); static void gst_rtpdec_handle_control_packet(GstRtpdec* element, char* data, int data_size); @@ -101,6 +105,9 @@ static void gst_rtpdec_set_clock(GstElement* element, GstClock* clock); +static void gst_rtpdec_send_report_thread(gpointer ptr); /* End of declarations */ static GstElementClass *parent_class = NULL; @@ -153,6 +160,7 @@ gobject_class->get_property = gst_rtpdec_get_property; gstelement_class->set_clock = gst_rtpdec_set_clock; + gstelement_class->release_locks = gst_rtpdec_release_locks; gst_rtpdec_class->default_mapping = gst_rtpdec_create_av_mapping(); } @@ -184,17 +192,15 @@ result = g_hash_table_new(g_int_hash, g_int_equal); for (i = 0; i < sizeof(fixed_payloads)/sizeof(struct fixed_payload); i++) { int* number; - struct payload_desc* payload_desc = g_new(struct payload_desc, 1); - int* sample_rate; - int* num_channels; - payload_desc->properties = g_hash_table_new(g_str_hash, g_str_equal); - sample_rate = g_new(int, 1); - *sample_rate = fixed_payloads[i].sample_rate ; - g_hash_table_insert(payload_desc->properties, (gpointer) "sample-rate", (gpointer) sample_rate); - num_channels = g_new(int, 1); - *num_channels = fixed_payloads[i].num_channels; - g_hash_table_insert(payload_desc->properties, (gpointer) "channels", (gpointer) num_channels); - g_hash_table_insert(payload_desc->properties, (gpointer) "name", (gpointer) fixed_payloads[i].name); + GValue sample_rate, num_channels; + GstStructure* payload_desc + g_value_init(&sample_rate, G_TYPE_UINT); + g_value_set_uint(&sample_rate, fixed_payloads[i].sample_rate); + g_value_init(&num_channels, G_TYPE_UINT); + g_value_set_uint(&num_channels, fixed_payloads[i].sample_rate); + payload_desc = gst_structure_new(fixed_payloads[i].name, + "sample-rate", sample_rate, + "num-channels", num_channels); number = g_new(int, 1); *number = 0; g_hash_table_insert(result, (gpointer) number, (gpointer) payload_desc); @@ -205,14 +211,28 @@ static void gst_rtpdec_init (GstRtpdec *element) { - element->sinkpad = gst_pad_new_from_template (gst_rtpdec_src_factory (), - "sink"); - gst_element_add_pad (GST_ELEMENT (element), element->sinkpad); - gst_pad_set_chain_function(element->sinkpad, gst_rtpdec_chain); + GError* error; element->clock = NULL; + element->bootpad = gst_pad_new("src", GST_PAD_SRC); + gst_element_add_pad(GST_ELEMENT(element), element->bootpad); + gst_pad_set_get_function(element->bootpad, gst_rtpdec_get); + element->myid = create_id(); + g_thread_create(gst_rtpdec_send_report_thread, element, TRUE, &error); + if (error != NULL) { + g_warning("Cannot perform sender reports"); + } +static void +gst_rtpdec_main_loop(GstElement* element) +{ + +} gst_rtpdec_chain(GstPad* pad, GstBuffer* buffer) @@ -562,28 +582,30 @@ static gboolean gst_rtpdec_change_payload_type(GstRtpdec* element, struct sender_info* sender_info, gchar payload_type) - struct payload_desc* payload_desc; + GstStructure* payload_desc; payload_desc = NULL; if (element->mapping) { - payload_desc = (struct payload_desc*) g_hash_table_lookup(element->mapping, (gconstpointer) &payload_type); + payload_desc = (GstStructure*) g_hash_table_lookup(element->mapping, (gconstpointer) &payload_type); } if (payload_desc == NULL) { - payload_desc = (struct payload_desc*) g_hash_table_lookup(GST_RTPDEC_GET_CLASS(element)->default_mapping, (gconstpointer) &payload_type); + payload_desc = (GstStructure*) g_hash_table_lookup(GST_RTPDEC_GET_CLASS(element)->default_mapping, (gconstpointer) &payload_type); return FALSE; /* Set sample rate */ { - unsigned int* sample_rate_ptr; - sample_rate_ptr = (unsigned int*) g_hash_table_lookup(payload_desc->properties, "sample-rate"); + GValue* sample_rate; + guint sample_rate; + sample_rate = gst_structure_get_value(payload_desc, "sample-rate"); if (sample_rate_ptr == NULL) { /* A bad entry for this payload type. It should have that property */ return FALSE; } - sender_info->sample_rate = *sample_rate_ptr; + sample_rate = g_value_get_uint(sample_rate); + sender_info->sample_rate = sample_rate; - /* Create the new element */ + /* Create the new handler */ GstElement* handler_element; GString* handler_name; @@ -608,9 +630,9 @@ sender_info->handler = GST_IRTPDEC_HANDLER(handler_element); - GstCaps* caps = gst_caps_new("rtpdec-out", payload_desc->mime_type, gst_props_empty_new()); - gst_irtpdec_set_caps_properties(caps, payload_desc->properties); - gst_pad_try_set_caps(sender_info->output, caps); + GstCaps* caps = gst_caps_new_empty(); + gst_caps_append_structure(caps, payload_desc); + gst_pad_try_set_caps(sender_info->out, caps); return TRUE; @@ -791,6 +813,42 @@ +gst_rtpdec_send_report_thread(gpointer ptr) + GstRtpdec* rtpdec = (GstRtpdec*) ptr; + gboolean do_exit; + guint wait_time; + while(1) { + wait_time = gst_rtpdec_get_interval_for_report(rtpdec); + do_exit = gst_rtpdec_wait(rtpdec, wait_time); + if (do_exit){ + break; + } + gst_rtpdec_send_report(rtpdec); +static guint +gst_rtpdec_get_interval_for_report(GstRtpdec* rtpdec) +static gboolean +gst_rtpdec_wait(GstRtpdec* rtpdec, guint wait_time) +gst_rtpdec_send_report(GstRtpdec* rtpdec) /* entry point to initialize the plug-in * initialize the plug-in itself * register the element factories and pad templates @@ -799,21 +857,9 @@ rtpdec_init (GModule *module, GstPlugin *plugin) - GstElementFactory *factory; - factory = gst_element_factory_new ("rtpdec", GST_RTPDEC_TYPE, - &rtpdec_details); - g_return_val_if_fail (factory != NULL, FALSE); - gst_element_factory_add_pad_template (factory, - gst_rtpdec_src_factory ()); - gst_rtpdec_sink_factory ()); - gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); - /* plugin initialisation succeeded */ - return TRUE; + gboolean sucess; + sucess = gst_element_register(plugin, "rtpdec", GST_RANK_PRIMARY, GST_TYPE_RTPDEC); + return sucess; /* this is the structure that gst-register looks for Index: gstrtpdec.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h,v --- a/gstrtpdec.h 27 Feb 2004 04:19:26 -0000 1.1 +++ b/gstrtpdec.h 27 Feb 2004 04:47:28 -0000 1.2 @@ -38,17 +38,9 @@ typedef struct _GstRtpdecHandler GstRtpdecHandler; -void gst_rtpdec_handler_get_data_packet(GstRtpdecHandler* handler, GstBuffer* buffer, unsigned int data_offset); -void gst_rtpdec_handler_get_app_packet(GstRtpdecHandler* handler, guint32 type, gconstpointer data, unsigned int data_size); -struct payload_desc { - gchar* mime_type; - GHashTable* properties; -}; struct sender_info { guint32 magic; + struct sockaddr_in6 socket; gboolean received_data; gboolean received_srvctl; unsigned int total_packets_received; /* According to us */ @@ -84,13 +76,9 @@ struct _GstRtpdec GstElement element; - GstPad* sinkpad; /* mapping of payload byte => payload_desc */ GHashTable* mapping; guint32 myid; - float fraction_rtcp_traffic; - float senders_rtcp_traffic; /* Mapping of identifier -> sender_info */ GHashTable* sender_list; @@ -101,6 +89,16 @@ GString* email; GstClock* clock; + /* Information for scheduling the sending of control info */ + gboolean no_report_sent; + guint bandwith; /* in bytes/second */ + /* Rules: if there are less than 25 % of senders + senders get 25 % of bandwidth */ + guint num_senders; + guint num_clients; + guint avg_rtcp_packet_length; + GHashTable* mapping; /* mapping of payload byte to caps */ struct _GstRtpdecClass --- NEW FILE: ntohll.h --- extern long long ntohll(long long n); |
From: Ramon G. F. <ra...@pd...> - 2004-02-27 05:27:24
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Thu Feb 26 2004 21:25:05 PST Log message: Splitting files; integrating functionality from UDP here Modified files: rtpdec : gstrtpdec.c gstrtpdec.h Added files: rtpdec : packet_type.h rtp_report.c rtp_report.h rtpdec.c rtpdec.h socket_fns.c socket_fns.h Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c.diff?r1=1.2&r2=1.3 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h.diff?r1=1.2&r2=1.3 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/packet_type.h?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_report.c?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_report.h?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtpdec.c?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtpdec.h?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/socket_fns.c?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/socket_fns.h?rev=1.1&content-type=text/vnd.viewcvs-markup ====Begin Diffs==== Index: gstrtpdec.c =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- a/gstrtpdec.c 27 Feb 2004 04:47:28 -0000 1.2 +++ b/gstrtpdec.c 27 Feb 2004 05:24:52 -0000 1.3 @@ -15,6 +15,8 @@ #include <assert.h> #include "gstrtpdec.h" +#include "rtpdec.h" +#include "rtp_report.h" static GstElementDetails rtpdec_details = { "Rtpdec", @@ -66,42 +68,6 @@ static void gst_rtpdec_main_loop(GstElement* element); -static void gst_rtpdec_chain(GstPad* pad, GstBuffer* buffer); - -static void gst_rtpdec_handle_control_packet(GstRtpdec* element, char* data, int data_size); -static void gst_rtpdec_handle_rtcp_sender_report(GstRtpdec* element, struct rtcp_sender_report* packet); -static void gst_rtpdec_handle_rtcp_recv_report(GstRtpdec* element, struct rtcp_recv_report* packet); -static void gst_rtpdec_handle_recv_block(GstRtpdec* element, struct reception_block* packet); -static void gst_rtpdec_handle_rtcp_sdes(GstRtpdec* element, struct rtcp_sdes* packet); -static void gst_rtpdec_handle_rtcp_bye(GstRtpdec* element, struct rtcp_bye* packet); -static void gst_rtpdec_handle_rtcp_app(GstRtpdec* element, struct rtcp_app* packet); -static unsigned int gst_rtpdec_rtcp_section_size(struct rtcp_common_header* packet); -static void gst_rtpdec_handle_data_packet(GstRtpdec* element, GstBuffer* buffer); -static gboolean gst_rtpdec_change_payload_type(GstRtpdec* element, struct sender_info* sender_info, gchar payload_type); -static struct sender_info* gst_rtpdec_get_sender_info(GstRtpdec* element, guint32 identifier, gboolean create_if_new); -static void gst_rtpdec_remove_sender(GstRtpdec* element, guint32 identifier); -static struct recv_info* gst_rtpdec_get_recv_info(GstRtpdec* element, guint32 identifier); -static void gst_rtpdec_set_recv_info_item_cname(struct recv_info* recv_info, gchar* text, unsigned int length); -static void gst_rtpdec_set_recv_info_item_name(struct recv_info* recv_info, gchar* text, unsigned int length); -static void gst_rtpdec_set_recv_info_item_email(struct recv_info* recv_info, gchar* text, unsigned int length); -static void gst_rtpdec_remove_receiver(GstRtpdec* element, guint32 identifier); static void gst_rtpdec_set_clock(GstElement* element, GstClock* clock); @@ -112,8 +78,6 @@ static GstElementClass *parent_class = NULL; -typedef enum { GST_RTPDEC_CONTROL = 100 } GstRtpEventType; GType gst_rtpdec_get_type (void) @@ -166,56 +130,15 @@ -static GHashTable* -gst_rtpdec_create_av_mapping() -{ - GHashTable* result; - struct fixed_payload { - int number; - const char* name; - int sample_rate; - int num_channels; - }; - struct fixed_payload fixed_payloads[] = { - {.number = 0, .name = "audio/pcmu", .sample_rate = 8000, .num_channels = 1}, - {.number = 3, .name = "audio/gsm", .sample_rate = 8000, .num_channels = 1}, - {.number = 4, .name = "audio/g723", .sample_rate = 8000, .num_channels = 1}, - {.number = 5, .name = "audio/dvi4", .sample_rate = 8000, .num_channels = 1}, - {.number = 6, .name = "audio/dvi4", .sample_rate = 16000,.num_channels = 1}, - {.number = 7, .name = "audio/lpc", .sample_rate = 8000, .num_channels = 1}, - {.number = 8, .name = "audio/pcma", .sample_rate = 8000, .num_channels = 1}, - {.number = 9, .name = "audio/g722", .sample_rate = 8000, .num_channels = 1}, - {.number =10, .name = "audio/l16", .sample_rate = 44100,.num_channels = 2}, - {.number =11, .name = "audio/l16", .sample_rate = 44100,.num_channels = 1} - unsigned int i; - result = g_hash_table_new(g_int_hash, g_int_equal); - for (i = 0; i < sizeof(fixed_payloads)/sizeof(struct fixed_payload); i++) { - int* number; - GValue sample_rate, num_channels; - GstStructure* payload_desc - g_value_init(&sample_rate, G_TYPE_UINT); - g_value_set_uint(&sample_rate, fixed_payloads[i].sample_rate); - g_value_init(&num_channels, G_TYPE_UINT); - g_value_set_uint(&num_channels, fixed_payloads[i].sample_rate); - payload_desc = gst_structure_new(fixed_payloads[i].name, - "sample-rate", sample_rate, - "num-channels", num_channels); - number = g_new(int, 1); - *number = 0; - g_hash_table_insert(result, (gpointer) number, (gpointer) payload_desc); - } - return result; -} static void -gst_rtpdec_init (GstRtpdec *element) +gst_rtpdec_init (GstRtpdec *rtpdec) { GError* error; - element->clock = NULL; - element->bootpad = gst_pad_new("src", GST_PAD_SRC); - gst_element_add_pad(GST_ELEMENT(element), element->bootpad); - gst_pad_set_get_function(element->bootpad, gst_rtpdec_get); + GstElement *element; + element = GST_ELEMENT(rtpdec); + rtpdec->clock = NULL; + gst_element_set_loop_function(element, gst_rtpdec_main_loop); element->myid = create_id(); g_thread_create(gst_rtpdec_send_report_thread, element, TRUE, &error); if (error != NULL) { @@ -224,555 +147,30 @@ } -static void -gst_rtpdec_main_loop(GstElement* element) - -gst_rtpdec_chain(GstPad* pad, GstBuffer* buffer) - GstRtpdec* element; - element = GST_RTPDEC(GST_OBJECT_PARENT(pad)); - g_return_if_fail (element != NULL); - g_return_if_fail (GST_IS_RTPDEC (element)); - if (GST_IS_EVENT(buffer)) { - GstEvent* event = GST_EVENT(buffer); - if (event->type == GST_RTPDEC_CONTROL) { - struct rtp_ctl_event_data* ctl_data = (struct rtp_ctl_event_data*) &event->event_data; - gst_rtpdec_handle_control_packet(element, ctl_data->data, ctl_data->size); - gst_event_unref(event); - } else { - gst_pad_event_default(pad, event); - } - } else { - gst_rtpdec_handle_data_packet(element, buffer); -static void -gst_rtpdec_handle_control_packet(GstRtpdec* element, char* data, int data_size) - while(1) { - char* current_packet = data; - unsigned int remaining_data = data_size; - struct rtcp_common_header* header; - unsigned int section_size; - if (remaining_data < sizeof(struct rtcp_common_header)) { - /* Corrupted packet */ - break; - header = (struct rtcp_common_header*) current_packet; - section_size = (ntohs(header->length) + 1)*4; - if (section_size > remaining_data) { - switch (header->packet_type) { - case SENDER_REPORT: - gst_rtpdec_handle_rtcp_sender_report(element, (struct rtcp_sender_report*) current_packet); - case RECEIVER_REPORT: - gst_rtpdec_handle_rtcp_recv_report(element, (struct rtcp_recv_report*) current_packet); - case SOURCE_DESCRIPTION: - gst_rtpdec_handle_rtcp_sdes(element, (struct rtcp_sdes*) current_packet); - case BYE: - gst_rtpdec_handle_rtcp_bye(element, (struct rtcp_bye*) current_packet); - case APP: - gst_rtpdec_handle_rtcp_app(element, (struct rtcp_app*) current_packet); - - if (section_size >= remaining_data) { - current_packet += section_size; - data_size -= section_size; - g_free(data); -gst_rtpdec_handle_rtcp_sender_report(GstRtpdec* element, struct rtcp_sender_report* packet) - guint32 sync_src; - guint32 packet_size; - struct sender_info* sender_info; - int num_recv; - packet_size = gst_rtpdec_rtcp_section_size(&packet->common); - if (packet_size < sizeof(struct rtcp_sender_report) + - (packet->common.num_sources - 1)*sizeof(struct reception_block)) { - return; - sync_src = ntohl(packet->sync_src_rtcp_sender); - sender_info = gst_rtpdec_get_sender_info(element, sync_src, TRUE); - sender_info->received_srvctl = TRUE; - sender_info->last_ctl_ntptime.integer = ntohl(packet->ntp_timestamp.integer); - sender_info->last_ctl_ntptime.frac = ntohl(packet->ntp_timestamp.frac); - sender_info->last_ctl_rtptimestamp = ntohl(packet->rtp_timestamp); - sender_info->total_packets_received = ntohl(packet->num_packets_sent); - gst_rtpdec_get_recv_info(element, sync_src); - for (num_recv = 0; num_recv <= packet->common.num_sources; num_recv++) { - gst_rtpdec_handle_recv_block(element, &packet->reception_blocks[num_recv]); -gst_rtpdec_handle_rtcp_recv_report(GstRtpdec* element, struct rtcp_recv_report* packet) - unsigned int packet_size; - if (packet_size < sizeof(struct rtcp_recv_report) + - (packet->common.num_sources - 1)*sizeof(struct rtcp_recv_report)) { -gst_rtpdec_handle_recv_block(GstRtpdec* element, struct reception_block* block) - struct recv_info* foo; - foo = gst_rtpdec_get_recv_info(element, ntohl(block->identifier)); -gst_rtpdec_handle_rtcp_sdes(GstRtpdec* element, struct rtcp_sdes* packet) - struct sdes_chunk* this_chunk; - unsigned int num_chunks; - unsigned int total_size, remaining_size; - num_chunks = packet->common.num_sources; - total_size = gst_rtpdec_rtcp_section_size(&packet->common) - sizeof(packet->common); - this_chunk = &packet->chunks[0]; - remaining_size = total_size; - unsigned int item_remaining_size; - unsigned int this_chunk_size; - guint32 contrib_src; - struct recv_info* recv_info; - struct sdes_item* this_item; - if (remaining_size < (sizeof(struct sdes_chunk) - sizeof(struct sdes_item) + 1)) { - // FIXME: log invalid packet (source IP, ...) - contrib_src = ntohl(this_chunk->identifier); - recv_info = gst_rtpdec_get_recv_info(element, contrib_src); - item_remaining_size = remaining_size - sizeof(this_chunk->identifier); - this_chunk_size = remaining_size + sizeof(this_chunk->identifier); - this_item = &this_chunk->items[0]; - while(1) { - unsigned int this_item_size; - if (this_item->type == END){ - break; - } - /* Ensure that item->length is readable */ - if (item_remaining_size < - sizeof(struct sdes_item) - sizeof(this_item->text)){ - this_item_size = sizeof(struct sdes_item) + sizeof(this_item->text)* - (this_item->length - 1); - if (item_remaining_size < this_item_size) { - switch(this_item->type) { - case CNAME: - gst_rtpdec_set_recv_info_item_cname(recv_info, &this_item->text[0], this_item->length); - case NAME: - gst_rtpdec_set_recv_info_item_name(recv_info, &this_item->text[0], this_item->length); - case EMAIL: - gst_rtpdec_set_recv_info_item_email(recv_info, &this_item->text[0], this_item->length); - default: - this_chunk_size += this_item_size; - item_remaining_size -= this_item_size; - this_item = (struct sdes_item*) ((char*) this_item + this_item_size); - if (item_remaining_size <= 1) { - /* Round up to a multiple of 4*/ - this_chunk_size = (this_chunk_size + 3) % 4; - remaining_size -= this_chunk_size; - if (remaining_size == 0) { - this_chunk = (struct sdes_chunk*) ( (char*) this_chunk + this_chunk_size); -gst_rtpdec_handle_rtcp_bye(GstRtpdec* element, struct rtcp_bye* packet) - unsigned int num_srcs, total_size; - total_size = gst_rtpdec_rtcp_section_size(&packet->common); - num_srcs = packet->common.num_sources; - if (total_size < sizeof(*packet) + sizeof(packet->identifier[0])*(num_srcs - 1)) { - /* Invalid packet */ - for (i = 0; i < num_srcs; i++) { - guint32 id; - id = ntohl(packet->identifier[i]); - gst_rtpdec_remove_sender(element, id); - gst_rtpdec_remove_receiver(element, id); -gst_rtpdec_handle_rtcp_app(GstRtpdec* element, struct rtcp_app* packet) - guint32 identifier; - if (packet_size < sizeof(*packet) - sizeof(packet->data)) { - identifier = packet->identifier; - sender_info = gst_rtpdec_get_sender_info(element, identifier, FALSE); - gst_rtpdec_get_recv_info(element, identifier); - if (sender_info == NULL) { - if (sender_info->handler) { - gst_irtpdec_handler_get_app_packet(sender_info->handler, ntohl(packet->name), - packet->data, packet_size - sizeof(*packet) + sizeof(packet->data)); -static unsigned int -gst_rtpdec_rtcp_section_size(struct rtcp_common_header* packet) - unsigned int length; - length = (ntohs(packet->length) + 1)*4; - if (packet->padding == 1) { - length = ntohl(* (guint32*) ((char*) packet + length - sizeof(guint32))); - return length; -gst_rtpdec_handle_data_packet(GstRtpdec* element, GstBuffer* buffer) - struct rtp_packet* packet; - unsigned int payload_offset; - GstClockTime now; - guint32 this_data_timestamp; - GstClockTime buffer_timestamp; - if (GST_BUFFER_SIZE(buffer) < sizeof(struct rtp_packet)) { - packet = (struct rtp_packet*) GST_BUFFER_DATA(buffer); - packet_size = GST_BUFFER_SIZE(buffer); - packet_size = ntohl(*(guint32 *)( (char*) packet + packet_size - sizeof(guint32))); - payload_offset = sizeof(struct rtp_packet) + (packet->num_contrib_sources - 1)*sizeof(unsigned long); - if (packet_size < payload_offset) { - if (packet->extension) { - struct rtp_packet_extension* extension = (struct rtp_packet_extension*) - ((char*) packet + packet->extension); - packet_size += sizeof(struct rtp_packet_extension) + ntohs(extension->length); - identifier = ntohl(packet->identifier); - sender_info = gst_rtpdec_get_sender_info(element, identifier, TRUE); - /* Update statistics */ - sender_info->total_packets_received++; - /* FIXME: byte count should include IP headers */ - sender_info->total_bytes_received += GST_BUFFER_SIZE(buffer); - sender_info->bytes_received += GST_BUFFER_SIZE(buffer); - sender_info->packets_received++; - if (sender_info->received_data) { - guint16 num_packets_lost; - /* Be careful with cycling numbers */ - num_packets_lost = ntohs(packet->sequence_number) - sender_info->last_sequence_number - (guint16) 1; - sender_info->total_packets_lost += num_packets_lost; - sender_info->packets_lost += num_packets_lost; - now = gst_clock_get_time(element->clock); - this_data_timestamp = ntohl(packet->timestamp); - GstClockTimeDiff time_diff; - guint32 new_diff; - time_diff = now - sender_info->time_last_data_packet_received; - if (sender_info->sample_rate != 0) { - new_diff = abs(time_diff*sender_info->sample_rate/GST_SECOND - - (this_data_timestamp - sender_info->last_data_timestamp)); - new_diff = 0; - sender_info->jitter = sender_info->jitter + - (new_diff - sender_info->jitter)/16; - sender_info->last_data_timestamp = this_data_timestamp; - sender_info->time_last_data_packet_received = now; - sender_info->received_data = TRUE; - sender_info->last_sequence_number = ntohs(packet->sequence_number); - if (!sender_info->received_srvctl) { - /* FIXME: For now we ignore data packets if we didn't receive - a control packet because then we cannot know the correct timestamp. - Perhaps there should be a better policy */ - if (sender_info->output == NULL) { - sender_info->output = gst_pad_new_from_template(GST_PAD_TEMPLATE_GET(gst_rtpdec_src_factory), - g_strdup_printf("src_%d", identifier)); - gst_element_add_pad(GST_ELEMENT(element), sender_info->output); - if (sender_info->payload_type != packet->payload_type) { - if (!gst_rtpdec_change_payload_type(element, sender_info, packet->payload_type)) { - /* We do not know how to handle this payload type. Exit */ - return; - assert(sender_info->handler != NULL); - if (sender_info->sample_rate == 0) { - sender_info->sample_rate = gst_irtpdec_handler_get_sample_rate(sender_info->handler, - buffer, payload_offset); - if (sender_info->sample_rate == 0) { - /* Unknown sample rate */ - /* FIXME: Handle years larger than 2038. Interpret ntptime according to the current year */ - buffer_timestamp = ((guint64) this_data_timestamp - sender_info->last_ctl_rtptimestamp)*GST_SECOND/sender_info->sample_rate + - ((guint64) sender_info->last_ctl_ntptime.integer)*GST_SECOND + - (((guint64) sender_info->last_ctl_ntptime.frac)*GST_SECOND << 32) ; - gst_irtpdec_handler_get_data_packet(sender_info->handler, buffer, payload_offset, buffer_timestamp); -static gboolean -gst_rtpdec_change_payload_type(GstRtpdec* element, struct sender_info* sender_info, gchar payload_type) - GstStructure* payload_desc; - payload_desc = NULL; - if (element->mapping) { - payload_desc = (GstStructure*) g_hash_table_lookup(element->mapping, (gconstpointer) &payload_type); - if (payload_desc == NULL) { - payload_desc = (GstStructure*) g_hash_table_lookup(GST_RTPDEC_GET_CLASS(element)->default_mapping, (gconstpointer) &payload_type); - return FALSE; - /* Set sample rate */ - { - GValue* sample_rate; - guint sample_rate; - sample_rate = gst_structure_get_value(payload_desc, "sample-rate"); - if (sample_rate_ptr == NULL) { - /* A bad entry for this payload type. It should have that property */ - return FALSE; - sample_rate = g_value_get_uint(sample_rate); - sender_info->sample_rate = sample_rate; - /* Create the new handler */ - GstElement* handler_element; - GString* handler_name; - handler_name = g_string_sized_new(20); - g_string_append_len(handler_name, "rtp-", sizeof("rtp-")); - g_string_append(handler_name, payload_desc->mime_type); - handler_element = gst_element_factory_make(handler_name->str, NULL); - if (handler_element == NULL || GST_IS_IRTPDEC_HANDLER(handler_element)) { - /* Could not find a handler for this type */ - g_string_free(handler_name, TRUE); - if (handler_element != NULL) { - gst_object_unref(GST_OBJECT(handler_element)); - if (sender_info->handler_element) { - gst_object_unref(GST_OBJECT(sender_info->handler_element)); - sender_info->handler_element = NULL; - sender_info->handler = NULL; - sender_info->handler_element = handler_element; - sender_info->handler = GST_IRTPDEC_HANDLER(handler_element); - GstCaps* caps = gst_caps_new_empty(); - gst_caps_append_structure(caps, payload_desc); - gst_pad_try_set_caps(sender_info->out, caps); - return TRUE; -static struct sender_info* -gst_rtpdec_get_sender_info(GstRtpdec* element, guint32 id, gboolean create_if_new) - struct sender_info* result; - result = (struct sender_info *) g_hash_table_lookup(element->sender_list, (gconstpointer)&id); - if (result == NULL) { - if (create_if_new) { - guint32* ptr_id = g_new(guint32, 1); - *ptr_id = id; - result = g_new(struct sender_info, 1); - result->magic = sender_magic; - result->received_srvctl = FALSE; - result->received_data = FALSE; - result->total_packets_received = 0; - result->total_packets_sent = 0; - result->total_packets_lost = 0; - result->total_bytes_received = 0; - result->jitter = 0.0; - result->packets_received = 0.0; - result->packets_lost = 0; - result->bytes_received = 0; - result->last_ctl_ntptime = (struct ntptime) {0, 0}; - result->last_ctl_rtptimestamp = 0; - result->output = NULL; - result->sample_rate = 0; - result->payload_type = 0; - result->handler = NULL; - result->handler_element = NULL; - g_hash_table_insert(element->sender_list, (gpointer) ptr_id, (gpointer) result); - assert(result->magic == sender_magic); -gst_rtpdec_remove_sender(GstRtpdec* element, guint32 identifier) +static guint32 +create_id() - guint32* stored_identifier; - gboolean found; - gpointer stored_identifier_gptr; - gpointer sender_info_gptr; - found = g_hash_table_lookup_extended(element->sender_list, (gconstpointer) &identifier, - &stored_identifier_gptr, &sender_info_gptr); - stored_identifier = (guint32 *) stored_identifier_gptr; - sender_info = (struct sender_info*) sender_info_gptr; - if (found) { - if (sender_info->output != NULL) { - GstPad* peer; - peer = GST_PAD_PEER(sender_info->output); - if (peer) { - gst_pad_unlink(sender_info->output, peer); - gst_element_remove_pad(GST_ELEMENT(element), sender_info->output); - gst_object_unref(GST_OBJECT(sender_info->output)); - gst_object_unref(GST_OBJECT(sender_info->handler)); - g_free(sender_info); - g_free(stored_identifier); - g_hash_table_remove(element->sender_list, (gconstpointer) &identifier); + GTimeVal time; + g_get_current_time(&time); + srandom(time.tv_sec + time.tv_usec); + return (guint32) random(); -static struct recv_info* -gst_rtpdec_get_recv_info(GstRtpdec* element, guint32 identifier) - struct recv_info* result; - result = (struct recv_info*) g_hash_table_lookup(element->recv_list, (gconstpointer) &identifier); - struct recv_info* result = g_new(struct recv_info, 1); - result->magic = recv_magic; - result->cname = NULL; - result->name = NULL; - result->email = NULL; - assert(result->magic == recv_magic); -gst_rtpdec_remove_receiver(GstRtpdec* element, guint32 identifier) +gst_rtpdec_main_loop(GstElement* element) - gpointer result_gptr; - found = g_hash_table_lookup_extended(element->recv_list, (gconstpointer) &identifier, - &stored_identifier_gptr, &result_gptr); - stored_identifier = (guint32*) stored_identifier_gptr; - result = (struct recv_info*) result_gptr; - assert(result != NULL); - if (result->cname != NULL) { - g_string_free(result->cname, TRUE); - if (result->name != NULL) { - g_string_free(result->name, TRUE); - if (result->email != NULL) { - g_string_free(result->email, TRUE); + guint data_size; + gchar* data; + struct sockaddr_in6 peer; + packet_type type; + while (wait_for_data(element, &data_size, &data, &peer, &type)) { + gst_rtpdec_dispatch_packet(data_size, data, &peer, type); } -gst_rtpdec_set_recv_info_item_cname(struct recv_info* recv_info, gchar* text, unsigned int length) - if (recv_info->cname != NULL) { - g_string_free(recv_info->cname, TRUE); - recv_info->cname = g_string_new_len(text, length); -gst_rtpdec_set_recv_info_item_name(struct recv_info* recv_info, gchar* text, unsigned int length) - if (recv_info->name != NULL) { - g_string_free(recv_info->name, TRUE); - recv_info->name = g_string_new_len(text, length); -gst_rtpdec_set_recv_info_item_email(struct recv_info* recv_info, gchar* text, unsigned int length) - if (recv_info->email != NULL) { - g_string_free(recv_info->email, TRUE); - recv_info->email = g_string_new_len(text, length); gst_rtpdec_set_clock(GstElement* element, GstClock* clock) @@ -813,41 +211,6 @@ -gst_rtpdec_send_report_thread(gpointer ptr) - GstRtpdec* rtpdec = (GstRtpdec*) ptr; - gboolean do_exit; - guint wait_time; - wait_time = gst_rtpdec_get_interval_for_report(rtpdec); - do_exit = gst_rtpdec_wait(rtpdec, wait_time); - if (do_exit){ - gst_rtpdec_send_report(rtpdec); -static guint -gst_rtpdec_get_interval_for_report(GstRtpdec* rtpdec) -gst_rtpdec_wait(GstRtpdec* rtpdec, guint wait_time) -gst_rtpdec_send_report(GstRtpdec* rtpdec) /* entry point to initialize the plug-in * initialize the plug-in itself Index: gstrtpdec.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h,v --- a/gstrtpdec.h 27 Feb 2004 04:47:28 -0000 1.2 +++ b/gstrtpdec.h 27 Feb 2004 05:24:52 -0000 1.3 @@ -99,6 +99,18 @@ guint num_clients; guint avg_rtcp_packet_length; GHashTable* mapping; /* mapping of payload byte to caps */ + + /* Network stuff */ + int control_socket, data_socket; + GstAddress local_address; + gboolean raw_local_address_uptodate; + GstNumAddress raw_local_address; + }; struct _GstRtpdecClass --- NEW FILE: packet_type.h --- typedef enum {data, control} packet_type; --- NEW FILE: rtp_report.c --- #include "rtp-report.h" #include "gstrtpdec.h" static void gst_rtpdec_send_report_thread(gpointer ptr) { GstRtpdec* rtpdec = (GstRtpdec*) ptr; gboolean do_exit; guint wait_time; while(1) { wait_time = gst_rtpdec_get_interval_for_report(rtpdec); do_exit = gst_rtpdec_wait(rtpdec, wait_time); if (do_exit){ break; } gst_rtpdec_send_report(rtpdec); } } static guint gst_rtpdec_get_interval_for_report(GstRtpdec* rtpdec) static gboolean gst_rtpdec_wait(GstRtpdec* rtpdec, guint wait_time) gst_rtpdec_send_report(GstRtpdec* rtpdec) --- NEW FILE: rtp_report.h --- #include <glib/glib.h> void gst_rtp_send_report_thread(gpointer ptr); --- NEW FILE: rtpdec.c --- static void gst_rtpdec_handle_control_packet(GstRtpdec* element, char* data, int data_size); static void gst_rtpdec_handle_rtcp_sender_report(GstRtpdec* element, struct rtcp_sender_report* packet); static void gst_rtpdec_handle_rtcp_recv_report(GstRtpdec* element, struct rtcp_recv_report* packet); static void gst_rtpdec_handle_recv_block(GstRtpdec* element, struct reception_block* packet); static void gst_rtpdec_handle_rtcp_sdes(GstRtpdec* element, struct rtcp_sdes* packet); static void gst_rtpdec_handle_rtcp_bye(GstRtpdec* element, struct rtcp_bye* packet); static void gst_rtpdec_handle_rtcp_app(GstRtpdec* element, struct rtcp_app* packet); static unsigned int gst_rtpdec_rtcp_section_size(struct rtcp_common_header* packet); static void gst_rtpdec_handle_data_packet(GstRtpdec* element, GstBuffer* buffer); static gboolean gst_rtpdec_change_payload_type(GstRtpdec* element, struct sender_info* sender_info, gchar payload_type); static struct sender_info* gst_rtpdec_get_sender_info(GstRtpdec* element, guint32 identifier, gboolean create_if_new); static void gst_rtpdec_remove_sender(GstRtpdec* element, guint32 identifier); static struct recv_info* gst_rtpdec_get_recv_info(GstRtpdec* element, guint32 identifier); static void gst_rtpdec_set_recv_info_item_cname(struct recv_info* recv_info, gchar* text, unsigned int length); static void gst_rtpdec_set_recv_info_item_name(struct recv_info* recv_info, gchar* text, unsigned int length); static void gst_rtpdec_set_recv_info_item_email(struct recv_info* recv_info, gchar* text, unsigned int length); static void gst_rtpdec_remove_receiver(GstRtpdec* element, guint32 identifier); GHashTable* gst_rtpdec_create_av_mapping() GHashTable* result; struct fixed_payload { int number; const char* name; int sample_rate; int num_channels; }; struct fixed_payload fixed_payloads[] = { {.number = 0, .name = "audio/pcmu", .sample_rate = 8000, .num_channels = 1}, {.number = 3, .name = "audio/gsm", .sample_rate = 8000, .num_channels = 1}, {.number = 4, .name = "audio/g723", .sample_rate = 8000, .num_channels = 1}, {.number = 5, .name = "audio/dvi4", .sample_rate = 8000, .num_channels = 1}, {.number = 6, .name = "audio/dvi4", .sample_rate = 16000,.num_channels = 1}, {.number = 7, .name = "audio/lpc", .sample_rate = 8000, .num_channels = 1}, {.number = 8, .name = "audio/pcma", .sample_rate = 8000, .num_channels = 1}, {.number = 9, .name = "audio/g722", .sample_rate = 8000, .num_channels = 1}, {.number =10, .name = "audio/l16", .sample_rate = 44100,.num_channels = 2}, {.number =11, .name = "audio/l16", .sample_rate = 44100,.num_channels = 1} unsigned int i; result = g_hash_table_new(g_int_hash, g_int_equal); for (i = 0; i < sizeof(fixed_payloads)/sizeof(struct fixed_payload); i++) { int* number; GValue sample_rate, num_channels; GstStructure* payload_desc g_value_init(&sample_rate, G_TYPE_UINT); g_value_set_uint(&sample_rate, fixed_payloads[i].sample_rate); g_value_init(&num_channels, G_TYPE_UINT); g_value_set_uint(&num_channels, fixed_payloads[i].sample_rate); payload_desc = gst_structure_new(fixed_payloads[i].name, "sample-rate", sample_rate, "num-channels", num_channels); number = g_new(int, 1); *number = 0; g_hash_table_insert(result, (gpointer) number, (gpointer) payload_desc); return result; void gst_rtpdec_dispatch_packet(GstRtpdec* guint size, gchar* data, struct sockaddr_in6* source, packet_type* type) GstRtpdec* element; element = GST_RTPDEC(GST_OBJECT_PARENT(pad)); g_return_if_fail (element != NULL); g_return_if_fail (GST_IS_RTPDEC (element)); if (type == control) { struct rtp_ctl_event_data* ctl_data = (struct rtp_ctl_event_data*) data; gst_rtpdec_handle_control_packet(element, data, size); gst_event_unref(event); } else { gst_rtpdec_handle_data_packet(element, size, data); static void gst_rtpdec_handle_control_packet(GstRtpdec* element, char* data, int data_size) char* current_packet = data; unsigned int remaining_data = data_size; struct rtcp_common_header* header; unsigned int section_size; if (remaining_data < sizeof(struct rtcp_common_header)) { /* Corrupted packet */ header = (struct rtcp_common_header*) current_packet; section_size = (ntohs(header->length) + 1)*4; if (section_size > remaining_data) { switch (header->packet_type) { case SENDER_REPORT: gst_rtpdec_handle_rtcp_sender_report(element, (struct rtcp_sender_report*) current_packet); case RECEIVER_REPORT: gst_rtpdec_handle_rtcp_recv_report(element, (struct rtcp_recv_report*) current_packet); case SOURCE_DESCRIPTION: gst_rtpdec_handle_rtcp_sdes(element, (struct rtcp_sdes*) current_packet); case BYE: gst_rtpdec_handle_rtcp_bye(element, (struct rtcp_bye*) current_packet); case APP: gst_rtpdec_handle_rtcp_app(element, (struct rtcp_app*) current_packet); if (section_size >= remaining_data) { current_packet += section_size; data_size -= section_size; g_free(data); gst_rtpdec_handle_rtcp_sender_report(GstRtpdec* element, struct rtcp_sender_report* packet) guint32 sync_src; guint32 packet_size; struct sender_info* sender_info; int num_recv; packet_size = gst_rtpdec_rtcp_section_size(&packet->common); if (packet_size < sizeof(struct rtcp_sender_report) + (packet->common.num_sources - 1)*sizeof(struct reception_block)) { return; sync_src = ntohl(packet->sync_src_rtcp_sender); sender_info = gst_rtpdec_get_sender_info(element, sync_src, TRUE); sender_info->received_srvctl = TRUE; sender_info->last_ctl_ntptime.integer = ntohl(packet->ntp_timestamp.integer); sender_info->last_ctl_ntptime.frac = ntohl(packet->ntp_timestamp.frac); sender_info->last_ctl_rtptimestamp = ntohl(packet->rtp_timestamp); sender_info->total_packets_received = ntohl(packet->num_packets_sent); gst_rtpdec_get_recv_info(element, sync_src); for (num_recv = 0; num_recv <= packet->common.num_sources; num_recv++) { gst_rtpdec_handle_recv_block(element, &packet->reception_blocks[num_recv]); gst_rtpdec_handle_rtcp_recv_report(GstRtpdec* element, struct rtcp_recv_report* packet) unsigned int packet_size; if (packet_size < sizeof(struct rtcp_recv_report) + (packet->common.num_sources - 1)*sizeof(struct rtcp_recv_report)) { gst_rtpdec_handle_recv_block(GstRtpdec* element, struct reception_block* block) struct recv_info* foo; foo = gst_rtpdec_get_recv_info(element, ntohl(block->identifier)); gst_rtpdec_handle_rtcp_sdes(GstRtpdec* element, struct rtcp_sdes* packet) struct sdes_chunk* this_chunk; unsigned int num_chunks; unsigned int total_size, remaining_size; num_chunks = packet->common.num_sources; total_size = gst_rtpdec_rtcp_section_size(&packet->common) - sizeof(packet->common); this_chunk = &packet->chunks[0]; remaining_size = total_size; unsigned int item_remaining_size; unsigned int this_chunk_size; guint32 contrib_src; struct recv_info* recv_info; struct sdes_item* this_item; if (remaining_size < (sizeof(struct sdes_chunk) - sizeof(struct sdes_item) + 1)) { // FIXME: log invalid packet (source IP, ...) contrib_src = ntohl(this_chunk->identifier); recv_info = gst_rtpdec_get_recv_info(element, contrib_src); item_remaining_size = remaining_size - sizeof(this_chunk->identifier); this_chunk_size = remaining_size + sizeof(this_chunk->identifier); this_item = &this_chunk->items[0]; while(1) { unsigned int this_item_size; if (this_item->type == END){ break; } /* Ensure that item->length is readable */ if (item_remaining_size < sizeof(struct sdes_item) - sizeof(this_item->text)){ this_item_size = sizeof(struct sdes_item) + sizeof(this_item->text)* (this_item->length - 1); if (item_remaining_size < this_item_size) { switch(this_item->type) { case CNAME: gst_rtpdec_set_recv_info_item_cname(recv_info, &this_item->text[0], this_item->length); case NAME: gst_rtpdec_set_recv_info_item_name(recv_info, &this_item->text[0], this_item->length); case EMAIL: gst_rtpdec_set_recv_info_item_email(recv_info, &this_item->text[0], this_item->length); default: this_chunk_size += this_item_size; item_remaining_size -= this_item_size; this_item = (struct sdes_item*) ((char*) this_item + this_item_size); if (item_remaining_size <= 1) { /* Round up to a multiple of 4*/ this_chunk_size = (this_chunk_size + 3) % 4; remaining_size -= this_chunk_size; if (remaining_size == 0) { this_chunk = (struct sdes_chunk*) ( (char*) this_chunk + this_chunk_size); gst_rtpdec_handle_rtcp_bye(GstRtpdec* element, struct rtcp_bye* packet) unsigned int num_srcs, total_size; total_size = gst_rtpdec_rtcp_section_size(&packet->common); num_srcs = packet->common.num_sources; if (total_size < sizeof(*packet) + sizeof(packet->identifier[0])*(num_srcs - 1)) { /* Invalid packet */ for (i = 0; i < num_srcs; i++) { guint32 id; id = ntohl(packet->identifier[i]); gst_rtpdec_remove_sender(element, id); gst_rtpdec_remove_receiver(element, id); gst_rtpdec_handle_rtcp_app(GstRtpdec* element, struct rtcp_app* packet) guint32 identifier; if (packet_size < sizeof(*packet) - sizeof(packet->data)) { identifier = packet->identifier; sender_info = gst_rtpdec_get_sender_info(element, identifier, FALSE); gst_rtpdec_get_recv_info(element, identifier); if (sender_info == NULL) { if (sender_info->handler) { gst_irtpdec_handler_get_app_packet(sender_info->handler, ntohl(packet->name), packet->data, packet_size - sizeof(*packet) + sizeof(packet->data)); static unsigned int gst_rtpdec_rtcp_section_size(struct rtcp_common_header* packet) unsigned int length; length = (ntohs(packet->length) + 1)*4; if (packet->padding == 1) { length = ntohl(* (guint32*) ((char*) packet + length - sizeof(guint32))); return length; gst_rtpdec_handle_data_packet(GstRtpdec* element, guint packet_size, gchar* data) struct rtp_packet* packet; unsigned int payload_offset; GstClockTime now; guint32 this_data_timestamp; GstClockTime buffer_timestamp; if (packet_size < sizeof(struct rtp_packet)) { packet = (struct rtp_packet*) data; packet_size = ntohl(*(guint32 *)( (char*) packet + packet_size - sizeof(guint32))); payload_offset = sizeof(struct rtp_packet) + (packet->num_contrib_sources - 1)*sizeof(unsigned long); if (packet_size < payload_offset) { if (packet->extension) { struct rtp_packet_extension* extension = (struct rtp_packet_extension*) ((char*) packet + packet->extension); packet_size += sizeof(struct rtp_packet_extension) + ntohs(extension->length); identifier = ntohl(packet->identifier); sender_info = gst_rtpdec_get_sender_info(element, identifier, TRUE); /* Update statistics */ sender_info->total_packets_received++; /* FIXME: byte count should include IP headers */ sender_info->total_bytes_received += GST_BUFFER_SIZE(buffer); sender_info->bytes_received += GST_BUFFER_SIZE(buffer); sender_info->packets_received++; if (sender_info->received_data) { guint16 num_packets_lost; /* Be careful with cycling numbers */ num_packets_lost = ntohs(packet->sequence_number) - sender_info->last_sequence_number - (guint16) 1; sender_info->total_packets_lost += num_packets_lost; sender_info->packets_lost += num_packets_lost; now = gst_clock_get_time(element->clock); this_data_timestamp = ntohl(packet->timestamp); GstClockTimeDiff time_diff; guint32 new_diff; time_diff = now - sender_info->time_last_data_packet_received; if (sender_info->sample_rate != 0) { new_diff = abs(time_diff*sender_info->sample_rate/GST_SECOND - (this_data_timestamp - sender_info->last_data_timestamp)); } else { new_diff = 0; sender_info->jitter = sender_info->jitter + (new_diff - sender_info->jitter)/16; sender_info->last_data_timestamp = this_data_timestamp; sender_info->time_last_data_packet_received = now; sender_info->received_data = TRUE; sender_info->last_sequence_number = ntohs(packet->sequence_number); if (!sender_info->received_srvctl) { /* FIXME: For now we ignore data packets if we didn't receive a control packet because then we cannot know the correct timestamp. Perhaps there should be a better policy */ if (sender_info->output == NULL) { sender_info->output = gst_pad_new_from_template(GST_PAD_TEMPLATE_GET(gst_rtpdec_src_factory), g_strdup_printf("src_%d", identifier)); gst_element_add_pad(GST_ELEMENT(element), sender_info->output); if (sender_info->payload_type != packet->payload_type) { if (!gst_rtpdec_change_payload_type(element, sender_info, packet->payload_type)) { /* We do not know how to handle this payload type. Exit */ return; assert(sender_info->handler != NULL); if (sender_info->sample_rate == 0) { sender_info->sample_rate = gst_irtpdec_handler_get_sample_rate(sender_info->handler, buffer, payload_offset); if (sender_info->sample_rate == 0) { /* Unknown sample rate */ /* FIXME: Handle years larger than 2038. Interpret ntptime according to the current year */ buffer_timestamp = ((guint64) this_data_timestamp - sender_info->last_ctl_rtptimestamp)*GST_SECOND/sender_info->sample_rate + ((guint64) sender_info->last_ctl_ntptime.integer)*GST_SECOND + (((guint64) sender_info->last_ctl_ntptime.frac)*GST_SECOND << 32) ; gst_irtpdec_handler_get_data_packet(sender_info->handler, buffer, payload_offset, buffer_timestamp); gst_rtpdec_change_payload_type(GstRtpdec* element, struct sender_info* sender_info, gchar payload_type) GstStructure* payload_desc; payload_desc = NULL; if (element->mapping) { payload_desc = (GstStructure*) g_hash_table_lookup(element->mapping, (gconstpointer) &payload_type); if (payload_desc == NULL) { payload_desc = (GstStructure*) g_hash_table_lookup(GST_RTPDEC_GET_CLASS(element)->default_mapping, (gconstpointer) &payload_type); return FALSE; /* Set sample rate */ { GValue* sample_rate; guint sample_rate; sample_rate = gst_structure_get_value(payload_desc, "sample-rate"); if (sample_rate_ptr == NULL) { /* A bad entry for this payload type. It should have that property */ return FALSE; sample_rate = g_value_get_uint(sample_rate); sender_info->sample_rate = sample_rate; /* Create the new handler */ GstElement* handler_element; GString* handler_name; handler_name = g_string_sized_new(20); g_string_append_len(handler_name, "rtp-", sizeof("rtp-")); g_string_append(handler_name, payload_desc->mime_type); handler_element = gst_element_factory_make(handler_name->str, NULL); if (handler_element == NULL || GST_IS_IRTPDEC_HANDLER(handler_element)) { /* Could not find a handler for this type */ g_string_free(handler_name, TRUE); if (handler_element != NULL) { gst_object_unref(GST_OBJECT(handler_element)); if (sender_info->handler_element) { gst_object_unref(GST_OBJECT(sender_info->handler_element)); sender_info->handler_element = NULL; sender_info->handler = NULL; sender_info->handler_element = handler_element; sender_info->handler = GST_IRTPDEC_HANDLER(handler_element); GstCaps* caps = gst_caps_new_empty(); gst_caps_append_structure(caps, payload_desc); gst_pad_try_set_caps(sender_info->out, caps); return TRUE; static struct sender_info* gst_rtpdec_get_sender_info(GstRtpdec* element, guint32 id, gboolean create_if_new) struct sender_info* result; result = (struct sender_info *) g_hash_table_lookup(element->sender_list, (gconstpointer)&id); if (result == NULL) { if (create_if_new) { guint32* ptr_id = g_new(guint32, 1); *ptr_id = id; result = g_new(struct sender_info, 1); result->magic = sender_magic; result->received_srvctl = FALSE; result->received_data = FALSE; result->total_packets_received = 0; result->total_packets_sent = 0; result->total_packets_lost = 0; result->total_bytes_received = 0; result->jitter = 0.0; result->packets_received = 0.0; result->packets_lost = 0; result->bytes_received = 0; result->last_ctl_ntptime = (struct ntptime) {0, 0}; result->last_ctl_rtptimestamp = 0; result->output = NULL; result->sample_rate = 0; result->payload_type = 0; result->handler = NULL; result->handler_element = NULL; g_hash_table_insert(element->sender_list, (gpointer) ptr_id, (gpointer) result); assert(result->magic == sender_magic); gst_rtpdec_remove_sender(GstRtpdec* element, guint32 identifier) guint32* stored_identifier; gboolean found; gpointer stored_identifier_gptr; gpointer sender_info_gptr; found = g_hash_table_lookup_extended(element->sender_list, (gconstpointer) &identifier, &stored_identifier_gptr, &sender_info_gptr); stored_identifier = (guint32 *) stored_identifier_gptr; sender_info = (struct sender_info*) sender_info_gptr; if (found) { if (sender_info->output != NULL) { GstPad* peer; peer = GST_PAD_PEER(sender_info->output); if (peer) { gst_pad_unlink(sender_info->output, peer); gst_element_remove_pad(GST_ELEMENT(element), sender_info->output); gst_object_unref(GST_OBJECT(sender_info->output)); gst_object_unref(GST_OBJECT(sender_info->handler)); g_free(sender_info); g_free(stored_identifier); g_hash_table_remove(element->sender_list, (gconstpointer) &identifier); static struct recv_info* gst_rtpdec_get_recv_info(GstRtpdec* element, guint32 identifier) struct recv_info* result; result = (struct recv_info*) g_hash_table_lookup(element->recv_list, (gconstpointer) &identifier); struct recv_info* result = g_new(struct recv_info, 1); result->magic = recv_magic; result->cname = NULL; result->name = NULL; result->email = NULL; assert(result->magic == recv_magic); gst_rtpdec_remove_receiver(GstRtpdec* element, guint32 identifier) gpointer result_gptr; found = g_hash_table_lookup_extended(element->recv_list, (gconstpointer) &identifier, &stored_identifier_gptr, &result_gptr); stored_identifier = (guint32*) stored_identifier_gptr; result = (struct recv_info*) result_gptr; assert(result != NULL); if (result->cname != NULL) { g_string_free(result->cname, TRUE); if (result->name != NULL) { g_string_free(result->name, TRUE); if (result->email != NULL) { g_string_free(result->email, TRUE); gst_rtpdec_set_recv_info_item_cname(struct recv_info* recv_info, gchar* text, unsigned int length) if (recv_info->cname != NULL) { g_string_free(recv_info->cname, TRUE); recv_info->cname = g_string_new_len(text, length); gst_rtpdec_set_recv_info_item_name(struct recv_info* recv_info, gchar* text, unsigned int length) if (recv_info->name != NULL) { g_string_free(recv_info->name, TRUE); recv_info->name = g_string_new_len(text, length); gst_rtpdec_set_recv_info_item_email(struct recv_info* recv_info, gchar* text, unsigned int length) if (recv_info->email != NULL) { g_string_free(recv_info->email, TRUE); recv_info->email = g_string_new_len(text, length); --- NEW FILE: rtpdec.h --- #include "packet_type.h" GHashTable* gst_rtpdec_reate_av_mapping(); void gst_rtpdec_dispatch_packet(guint size, gchar* data, struct sockaddr_in6* source, packet_type* type); --- NEW FILE: socket_fns.c --- #include "socket_fns.h" gboolean wait_for_data(GstRtpdec* element, gunit* data_size, gchar** data, struct sockaddr_in6 *peer, packet_type* type) --- NEW FILE: socket_fns.h --- gunit* data_size, gchar** data, struct sockaddr_in6 *peer, packet_type* type); |
From: Ramon G. F. <ra...@pd...> - 2004-03-02 06:36:11
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Mon Mar 01 2004 22:31:25 PST Log message: Now it compiles Modified files: rtpdec : address.h gstrtpdec.c gstrtpdec.h packet_type.h rtp_report.c rtp_report.h rtpdec.c rtpdec.h socket_fns.h Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/address.h.diff?r1=1.1&r2=1.2 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c.diff?r1=1.3&r2=1.4 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h.diff?r1=1.3&r2=1.4 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/packet_type.h.diff?r1=1.1&r2=1.2 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_report.c.diff?r1=1.1&r2=1.2 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_report.h.diff?r1=1.1&r2=1.2 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtpdec.c.diff?r1=1.1&r2=1.2 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtpdec.h.diff?r1=1.1&r2=1.2 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/socket_fns.h.diff?r1=1.1&r2=1.2 ====Begin Diffs==== Index: address.h =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/address.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- a/address.h 27 Feb 2004 04:47:28 -0000 1.1 +++ b/address.h 2 Mar 2004 06:31:12 -0000 1.2 @@ -5,7 +5,7 @@ #include <netinet/in.h> struct _GstAddress { - enum {IPV4, IPV6, NAME} type; + enum {ADDR_IPV4, ADDR_IPV6, ADDR_NAME} type; union addr_fmt { struct in_addr ipv4_address; struct in6_addr ipv6_address; @@ -15,22 +15,9 @@ typedef struct _GstAddress GstAddress; -struct _GstAddrPort { - GstAddress addr; - unsigned short port; -}; - -typedef struct _GstAddrPort GstAddrPort; GType gst_address_get_type(); -GType gst_peer_get_type(); -GType gst_address_list_get_type(); -GType gst_addr_port_list_get_type(); #define GST_TYPE_ADDRESS (gst_address_get_type()) -#define GST_TYPE_ADDR_PORT (gst_addr_port_get_type()) -#define GST_TYPE_ADDRESS_LIST (gst_address_list_get_type()) -#define GST_TYPE_ADDR_PORT_LIST (gst_addr_port_list_get_type()) /* Represents the address of a single logical machine, @@ -38,43 +25,29 @@ It is the result of a name resolution that returns a list of addresses */ struct _GstNumAddress { - guint num_alternatives; - struct in6_addr* alternatives; + GArray* alternatives; /* Array of struct in6_addr */ }; typedef struct _GstNumAddress GstNumAddress; -/* Represents a list of addresses. For instance, a list of authorized machines */ -struct _GstNumAddresses { - GList* list; /* Actually, a GList of <GstNumAddress> */ +struct _GstAuthorizedAddr { + GstNumAddress addr; + in_port_t low, high; -typedef struct _GstNumAddresses GstNumAddresses; +typedef struct _GstAuthorizedAddr GstAuthorizedAddr; -struct _GstNumAddressPort { - GstNumAddress address; - guint16 port; +struct _GstAuthorizedAddrs { + GArray* authorized_addrs; -typedef struct _GstNumAddressPort GstNumAddressPort; -struct _GstNumAddressesPorts { - GList* list; /* GList of <GstNumAddressPort> */ -typedef struct _GstNumAddressesPorts GstNumAddressesPorts; +typedef struct _GstAuthorizedAddrs GstAuthorizedAddrs; void resolve_address(const GstAddress* address, GstNumAddress* result); -void resolve_addresses(const GList* addresses, /* GList of GstAddress */ - GstNumAddresses* result); -void resolve_addresses_ports(const GList* addresses, /* GList of GstAddrPort */ - GstNumAddressesPorts* result); gboolean try_bind(int socket, const GstNumAddress* address, int port); -void try_send(int socket, GstNumAddressPort* remote, const char* data, guint size); +void try_send(int socket, GstNumAddress* remote, in_port_t port, const char* data, guint size); #endif Index: gstrtpdec.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- a/gstrtpdec.c 27 Feb 2004 05:24:52 -0000 1.3 +++ b/gstrtpdec.c 2 Mar 2004 06:31:12 -0000 1.4 @@ -15,6 +15,7 @@ #include <assert.h> #include "gstrtpdec.h" +#include "socket_fns.h" #include "rtpdec.h" #include "rtp_report.h" @@ -39,12 +40,13 @@ enum { ARG_0, ARG_LOCAL_DATA_PORT, - ARG_LOCAL_DATA_ADDR, + ARG_LOCAL_CONTROL_PORT, ARG_LOCAL_ADDR, ARG_REMOTE_HOST, ARG_REMOTE_DATA_PORT, ARG_REMOTE_CONTROL_PORT, ARG_MULTICAST_ADDR, + ARG_AUTHORIZED_SENDERS, ARG_MEDIA_MIME_MAPPING, ARG_BANDWIDTH @@ -58,25 +60,22 @@ GST_STATIC_CAPS_ANY); static void gst_rtpdec_class_init(GstRtpdecClass *klass); -static GHashTable* gst_rtpdec_create_av_mapping(); + static void gst_rtpdec_init (GstRtpdec *filter); static void gst_rtpdec_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void gst_rtpdec_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void gst_rtpdec_main_loop(GstElement* element); static void gst_rtpdec_set_clock(GstElement* element, GstClock* clock); +static gboolean gst_rtpdec_release_locks(GstElement* element); -static void gst_rtpdec_send_report_thread(gpointer ptr); -/* End of declarations */ +static GstElementStateReturn gst_rtpdec_change_state(GstElement* element); -static GstElementClass *parent_class = NULL; +static gboolean rtpdec_init(GstPlugin* plugin); GType @@ -118,13 +117,12 @@ gst_rtpdec_class = (GstRtpdecClass*) klass; - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); gobject_class->set_property = gst_rtpdec_set_property; gobject_class->get_property = gst_rtpdec_get_property; gstelement_class->set_clock = gst_rtpdec_set_clock; gstelement_class->release_locks = gst_rtpdec_release_locks; + gstelement_class->change_state = gst_rtpdec_change_state; gst_rtpdec_class->default_mapping = gst_rtpdec_create_av_mapping(); } @@ -139,24 +137,33 @@ element = GST_ELEMENT(rtpdec); rtpdec->clock = NULL; gst_element_set_loop_function(element, gst_rtpdec_main_loop); - element->myid = create_id(); + rtpdec->myid = create_id(); g_thread_create(gst_rtpdec_send_report_thread, element, TRUE, &error); if (error != NULL) { g_warning("Cannot perform sender reports"); } -} + rtpdec->sender_list = NULL; + rtpdec->recv_list = NULL; + rtpdec->cname = NULL; + rtpdec->email = NULL; + rtpdec->no_report_sent = TRUE; + rtpdec->bandwith = 8000; + rtpdec->num_senders = 0; + rtpdec->num_clients = 0; + rtpdec->mapping = NULL; + rtpdec->control_socket = -1; + rtpdec->data_socket = -1; + rtpdec->data_port = -1; + rtpdec->control_port = -1; + rtpdec->remote_address.alternatives = NULL; + + rtpdec->default_authorized = TRUE; + rtpdec->authorized_senders.authorized_addrs = NULL; + rtpdec->mtu = G_MAXINT; -static guint32 -create_id() -{ - GTimeVal time; - g_get_current_time(&time); - srandom(time.tv_sec + time.tv_usec); - return (guint32) random(); static void gst_rtpdec_main_loop(GstElement* element) { @@ -164,14 +171,17 @@ gchar* data; struct sockaddr_in6 peer; packet_type type; - while (wait_for_data(element, &data_size, &data, &peer, &type)) { - gst_rtpdec_dispatch_packet(data_size, data, &peer, type); + GstRtpdec* rtpdec; + rtpdec = GST_RTPDEC(element); + g_assert(rtpdec != NULL); + while (wait_for_data(rtpdec, &data_size, &data, &peer, &type)) { + if (authorized_packet(rtpdec, &peer, &type)) { + gst_rtpdec_dispatch_packet(rtpdec, data_size, data, &peer, type); + } gst_rtpdec_set_clock(GstElement* element, GstClock* clock) @@ -182,13 +192,56 @@ gst_rtpdec_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) - GstRtpdec *filter; + GstRtpdec* filter; + int port_val; + GstAddress* addr; + GHashTable* mapping; + int bandwidth; g_return_if_fail (GST_IS_RTPDEC (object)); filter = GST_RTPDEC (object); switch (prop_id) { + case ARG_LOCAL_DATA_PORT: + port_val = g_value_get_int(value); + gst_rtpdec_set_data_port(port_val); + break; + case ARG_LOCAL_CONTROL_PORT: + gst_rtpdec_set_ctl_port(port_val); + case ARG_LOCAL_ADDR: + addr = (GstAddress*) g_value_get_boxed(value); + gst_rtpdec_set_local_addr(addr); + gst_address_free(addr); + case ARG_REMOTE_HOST: + gst_rtpdec_set_remote_addr(addr); + case ARG_REMOTE_DATA_PORT: + gst_rtpdec_set_remote_data_port(port_val); + case ARG_REMOTE_CONTROL_PORT: + gst_rtpdec_set_remote_ctl_port(port_val); + case ARG_MULTICAST_ADDR: + gst_rtpdec_set_multicast_addr(addr); + case ARG_MEDIA_MIME_MAPPING: + mapping = (GHashTable*) g_value_get_boxed(value); + gst_rtpdec_set_mapping(mapping); + case ARG_BANDWIDTH: + bandwidth = g_value_get_int(value); + gst_rtpdec_set_bandwith(value); default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -211,25 +264,51 @@ +static gboolean +gst_rtpdec_release_locks(GstElement* element) +{ + GstRtpdec* rtpdec = GST_RTPDEC(element); + char ctl[1]; + g_assert(element != NULL); + ctl[0] = 0; + write (rtpdec->pipe[0], ctl, 1); + return TRUE; +} +static GstElementStateReturn +gst_rtpdec_change_state(GstElement* element) + gboolean sucess; + if (GST_STATE_PENDING(element) == GST_STATE_NULL) { + gst_rtpdec_close_conn(element); + return GST_STATE_SUCCESS; + } + if (GST_STATE(element) == GST_STATE_NULL && GST_STATE_PENDING(element) != GST_STATE_NULL) { + sucess = gst_rtpdec_open_conn(element); + return sucess ? GST_STATE_SUCCESS : GST_STATE_FAILURE; -/* entry point to initialize the plug-in - * initialize the plug-in itself - * register the element factories and pad templates - * register the features - */ static gboolean -rtpdec_init (GModule *module, GstPlugin *plugin) +rtpdec_init (GstPlugin *plugin) gboolean sucess; - sucess = gst_element_register(plugin, "rtpdec", GST_RANK_PRIMARY, GST_TYPE_RTPDEC); + sucess = gst_element_register(plugin, "rtpdec", GST_RANK_PRIMARY, GST_RTPDEC_TYPE); return sucess; -/* this is the structure that gst-register looks for - * so keep the name plugin_desc, or you cannot get your plug-in registered */ -GstPluginDesc plugin_desc = { +GST_PLUGIN_DEFINE ( GST_VERSION_MAJOR, GST_VERSION_MINOR, "rtpdec", - rtpdec_init + "RTP decoding", + rtpdec_init, + VERSION, + "LGPL", + GST_PACKAGE, + GST_ORIGIN +) Index: gstrtpdec.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h,v --- a/gstrtpdec.h 27 Feb 2004 05:24:52 -0000 1.3 +++ b/gstrtpdec.h 2 Mar 2004 06:31:12 -0000 1.4 @@ -7,6 +7,7 @@ #include <glib/ghash.h> #include <glib/gstring.h> +#include "address.h" #include "rtp_packet.h" #include "rtp_ctl_event.h" #include "gstrtphandler.h" @@ -25,7 +26,7 @@ #define GST_IS_RTPDEC(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_RTPDEC_TYPE)) #define GST_IS_RTPDEC_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTPDEC)) + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_RTPDEC_TYPE)) #define GST_RTPDEC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_RTPDEC_TYPE, GstRtpdecClass)) typedef struct _GstRtpdec GstRtpdec; @@ -98,19 +99,25 @@ guint num_senders; guint num_clients; guint avg_rtcp_packet_length; - GHashTable* mapping; /* mapping of payload byte to caps */ /* Network stuff */ int control_socket, data_socket; - GstAddress local_address; + GstNumAddress local_address; + in_port_t data_port, control_port; - gboolean raw_local_address_uptodate; - GstNumAddress raw_local_address; + GstNumAddress remote_address; + in_port_t remote_data_port, remote_control_port; - + GstNumAddress multicast_addr; + gboolean default_authorized; + GstAuthorizedAddrs authorized_senders; + guint mtu; + /* Write to pipe[0] for interrupting any blocking operation */ + int pipe[2]; struct _GstRtpdecClass Index: packet_type.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/packet_type.h,v --- a/packet_type.h 27 Feb 2004 05:24:52 -0000 1.1 +++ b/packet_type.h 2 Mar 2004 06:31:12 -0000 1.2 @@ -1,2 +1,6 @@ -typedef enum {data, control} packet_type; +#ifndef __PACKET_TYPE_H__ +#define __PACKET_TYPE_H__ +typedef enum {data_packet, control_packet} packet_type; +#endif Index: rtp_report.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_report.c,v --- a/rtp_report.c 27 Feb 2004 05:24:52 -0000 1.1 +++ b/rtp_report.c 2 Mar 2004 06:31:12 -0000 1.2 @@ -2,7 +2,7 @@ -static void +gpointer gst_rtpdec_send_report_thread(gpointer ptr) GstRtpdec* rtpdec = (GstRtpdec*) ptr; Index: rtp_report.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_report.h,v --- a/rtp_report.h 27 Feb 2004 05:24:52 -0000 1.1 +++ b/rtp_report.h 2 Mar 2004 06:31:12 -0000 1.2 @@ -1,3 +1,6 @@ -#include <glib/glib.h> +#ifndef __RTP_REPORT_H__ +#define __RTP_REPORT_H__ 1 +#include <glib/gtypes.h> -void gst_rtp_send_report_thread(gpointer ptr); +gpointer gst_rtpdec_send_report_thread(gpointer ptr); Index: rtpdec.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtpdec.c,v --- a/rtpdec.c 27 Feb 2004 05:24:52 -0000 1.1 +++ b/rtpdec.c 2 Mar 2004 06:31:12 -0000 1.2 @@ -1,5 +1,3 @@ static void gst_rtpdec_handle_control_packet(GstRtpdec* element, char* data, int data_size); @@ -612,3 +610,14 @@ recv_info->email = g_string_new_len(text, length); +guint32 +create_id() + GTimeVal time; + g_get_current_time(&time); + srandom(time.tv_sec + time.tv_usec); + return (guint32) random(); Index: rtpdec.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtpdec.h,v --- a/rtpdec.h 27 Feb 2004 05:24:52 -0000 1.1 +++ b/rtpdec.h 2 Mar 2004 06:31:12 -0000 1.2 @@ -1,7 +1,16 @@ +#ifndef __RTPDEC_H__ +#define __RTPDEC_H__ +#include <glib/ghash.h> #include "packet_type.h" -GHashTable* gst_rtpdec_reate_av_mapping(); +GHashTable* gst_rtpdec_create_av_mapping(); +void gst_rtpdec_dispatch_packet(GstRtpdec* rtpdec, guint size, gchar* data, struct sockaddr_in6* source, packet_type type); -void gst_rtpdec_dispatch_packet(guint size, gchar* data, struct sockaddr_in6* source, packet_type* type); +void gst_rtpdec_set_mapping(GHashTable* mapping); +guint32 createid(void); Index: socket_fns.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/socket_fns.h,v --- a/socket_fns.h 27 Feb 2004 05:24:52 -0000 1.1 +++ b/socket_fns.h 2 Mar 2004 06:31:12 -0000 1.2 @@ -1,5 +1,31 @@ +#ifndef __SOCKET_FNS_H__ +#define __SOCKET_FNS_H__ gboolean wait_for_data(GstRtpdec* element, - gunit* data_size, gchar** data, struct sockaddr_in6 *peer, packet_type* type); + guint* data_size, gchar** data, struct sockaddr_in6 *peer, packet_type* type); +gboolean authorized_packet(GstRtpdec* element, struct sockaddr_in6* addr, packet_type* type); +void gst_rtpdec_set_data_port(guint port); +void gst_rtpdec_set_ctl_port(guint port); +void gst_rtpdec_set_local_addr(GstAddress* addr); +void gst_rtpdec_set_remote_addr(GstAddress* addr); +void gst_rtpdec_set_remote_data_port(guint port); +void gst_rtpdec_set_remote_ctl_port(guint port); +void gst_rtpdec_set_multicast_addr(GstAddress* addr); +gboolean gst_rtpdec_open_conn(GstElement* element); +void gst_rtpdec_close_conn(GstElement* element); |
From: Ramon G. F. <ra...@pd...> - 2004-03-02 14:02:53
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Tue Mar 02 2004 05:57:56 PST Log message: Stuff for scalable sending of RTCP packets (RFC3550) Modified files: rtpdec : gstrtpdec.h rtp_report.c Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h.diff?r1=1.4&r2=1.5 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_report.c.diff?r1=1.2&r2=1.3 ====Begin Diffs==== Index: gstrtpdec.h =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- a/gstrtpdec.h 2 Mar 2004 06:31:12 -0000 1.4 +++ b/gstrtpdec.h 2 Mar 2004 13:57:44 -0000 1.5 @@ -92,13 +92,16 @@ GstClock* clock; /* Information for scheduling the sending of control info */ - gboolean no_report_sent; guint bandwith; /* in bytes/second */ - /* Rules: if there are less than 25 % of senders - senders get 25 % of bandwidth */ - guint num_senders; - guint num_clients; - guint avg_rtcp_packet_length; + + GTime tp; /* last time when an RTCP packet was transmitted */ + GTime tn; /* next scheduled transsission of RTCP */ + guint members; + guint senders; + guint rtcp_bw; /* bandwidth for RTCP */ + /* we_sent is false */ + guint avg_rtcp_size; + gboolean initial; /* True if no RTCP packet yet sent */ /* Network stuff */ Index: rtp_report.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_report.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- a/rtp_report.c 2 Mar 2004 06:31:12 -0000 1.2 +++ b/rtp_report.c 2 Mar 2004 13:57:44 -0000 1.3 @@ -19,6 +19,36 @@ } +/* Rules for limiting RTCP control traffic bandwidth + Control bandwidth should be limited to 5 % of the total bandwidth available. + Of that, about 25 % should be reserved for senders (if senders are less than 25 %). + It is recommended that there should be at least 5 seconds between every report generation. + It is also recommended that half of the previous value should be waited at startup, + in order to get the right number of partners before the first packet delivery. + The fixed minimum can be reduced to 360/bandwidth for (a) senders in multicast transmissions, + (b) sender and receiver in unicast transmission. + Then, the interval between RTCP packets should be multiplied by a random factor in [0.5, 1.5]. + BYE packets should be sent inmediatly, except with a random delay to avoid a flood by + many simultaneous users. + Timer reconsideration: when + After a BYE packet is received one should not inmediatly remove the entry for that SSRC. + Instead, one should mark the entry for removal. Some delayed packets could arrive causing + the entry to be added. + If no packet has been received from a site in 5 reporting intervals, the site can be regarded + as closed. + When sending a bye packet: start a timeout, the send the packet. If during the timeout + more BYE packets are received, then increase the timeout accordinly. + Reverse reconsideration: after a bye packet is received, the next packet is delayed + in + +*/ static guint gst_rtpdec_get_interval_for_report(GstRtpdec* rtpdec) { |
From: Ramon G. F. <ra...@pd...> - 2004-03-02 22:58:28
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Tue Mar 02 2004 14:53:18 PST Log message: Some touches in initialization Modified files: rtpdec : address.h gstrtpdec.c gstrtpdec.h rtp_report.c rtpdec.c rtpdec.h Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/address.h.diff?r1=1.2&r2=1.3 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c.diff?r1=1.4&r2=1.5 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h.diff?r1=1.5&r2=1.6 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_report.c.diff?r1=1.3&r2=1.4 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtpdec.c.diff?r1=1.2&r2=1.3 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtpdec.h.diff?r1=1.2&r2=1.3 ====Begin Diffs==== Index: address.h =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/address.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- a/address.h 2 Mar 2004 06:31:12 -0000 1.2 +++ b/address.h 2 Mar 2004 22:53:06 -0000 1.3 @@ -30,6 +30,8 @@ typedef struct _GstNumAddress GstNumAddress; +GstNumAddress gst_addr_any(); + struct _GstAuthorizedAddr { GstNumAddress addr; in_port_t low, high; Index: gstrtpdec.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- a/gstrtpdec.c 2 Mar 2004 06:31:12 -0000 1.4 +++ b/gstrtpdec.c 2 Mar 2004 22:53:06 -0000 1.5 @@ -142,26 +142,43 @@ if (error != NULL) { g_warning("Cannot perform sender reports"); } - rtpdec->sender_list = NULL; - rtpdec->recv_list = NULL; - rtpdec->cname = NULL; + rtpdec->mapping = NULL; + rtpdec->sender_list = g_hash_table_new(g_int_hash, g_int_equal); + rtpdec->recv_list = g_hash_table_new(g_int_hash, g_int_equal); + rtpdec->cname = make_cname(); rtpdec->email = NULL; - rtpdec->no_report_sent = TRUE; + + rtpdec->clock = NULL; rtpdec->bandwith = 8000; - rtpdec->num_senders = 0; - rtpdec->num_clients = 0; - rtpdec->mapping = NULL; + rtpdec->members = 0; + rtpdec->senders = 0; + rtpdec->rtcp_bw = rtpdec->bandwith/20; + rtpdec->avg_rtcp_size = 0; + rtpdec->initial = 0; rtpdec->control_socket = -1; rtpdec->data_socket = -1; + rtpdec->local_address = gst_addr_any(); rtpdec->data_port = -1; rtpdec->control_port = -1; - rtpdec->remote_address.alternatives = NULL; - + rtpdec->remote_data_port = 5004; + rtpdec->remote_control_port = 5005; + rtpdec->multicast_addr.alternatives = NULL; rtpdec->default_authorized = TRUE; rtpdec->authorized_senders.authorized_addrs = NULL; rtpdec->mtu = G_MAXINT; + pipe(rtpdec->pipe); + pipe(rtpdec->report_thread_pipe); } static void Index: gstrtpdec.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h,v retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- a/gstrtpdec.h 2 Mar 2004 13:57:44 -0000 1.5 +++ b/gstrtpdec.h 2 Mar 2004 22:53:06 -0000 1.6 @@ -65,6 +65,7 @@ unsigned int payload_type; GstElement* handler_element; GstIRtpdecHandler* handler; + gboolean removed; /* a BYE packet was received */ }; struct recv_info { @@ -72,6 +73,7 @@ GString* name; GString* cname; GString* email; struct _GstRtpdec @@ -95,7 +97,7 @@ guint bandwith; /* in bytes/second */ GTime tp; /* last time when an RTCP packet was transmitted */ - GTime tn; /* next scheduled transsission of RTCP */ + GTime tn; /* next scheduled transmission of RTCP */ guint members; guint senders; guint rtcp_bw; /* bandwidth for RTCP */ @@ -108,7 +110,7 @@ int control_socket, data_socket; GstNumAddress local_address; - in_port_t data_port, control_port; + int data_port, control_port; GstNumAddress remote_address; in_port_t remote_data_port, remote_control_port; @@ -121,6 +123,9 @@ /* Write to pipe[0] for interrupting any blocking operation */ int pipe[2]; + /* Pipe for communicating with the thread that sends reports */ + int report_thread_pipe[2]; struct _GstRtpdecClass Index: rtp_report.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_report.c,v diff -u -d -r1.3 -r1.4 --- a/rtp_report.c 2 Mar 2004 13:57:44 -0000 1.3 +++ b/rtp_report.c 2 Mar 2004 22:53:06 -0000 1.4 @@ -16,6 +16,7 @@ } gst_rtpdec_send_report(rtpdec); + return NULL; Index: rtpdec.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtpdec.c,v --- a/rtpdec.c 2 Mar 2004 06:31:12 -0000 1.2 +++ b/rtpdec.c 2 Mar 2004 22:53:06 -0000 1.3 @@ -1,5 +1,6 @@ #include "gstrtpdec.h" static void gst_rtpdec_handle_control_packet(GstRtpdec* element, char* data, int data_size); static void gst_rtpdec_handle_rtcp_sender_report(GstRtpdec* element, struct rtcp_sender_report* packet); @@ -621,3 +622,32 @@ return (guint32) random(); +GString* +make_cname(void) +{ + GStrint* result; + char hostname[256], username[256]; + gethostname(hostname, sizeof(hostname) - 1); + hostname[255] = '\0'; + getusername(username, sizeof(username) - 1); + username[255] = '\0'; + result = g_string_new(); + g_string_append(result, hostname); + g_string_append(result, "@"); + g_string_append(result, username); + return result; +} +static void +getusername(char* buffer, guint buf_size) + char* env_name; + struct passwd* pass; + env_name = getenv("USER"); + if (env_name) { + strncpy(buffer, name, buf_size); + } else { + pass = getpwuid(getuid()); + strncpy(buffer, pass->name, buf_size); + } Index: rtpdec.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtpdec.h,v --- a/rtpdec.h 2 Mar 2004 06:31:12 -0000 1.2 +++ b/rtpdec.h 2 Mar 2004 22:53:06 -0000 1.3 @@ -13,4 +13,6 @@ void gst_rtpdec_set_mapping(GHashTable* mapping); guint32 createid(void); +GString* make_cname(void); #endif |
From: Ramon G. F. <ra...@pd...> - 2004-03-04 19:51:07
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Thu Mar 04 2004 11:44:50 PST Log message: new field Modified files: rtpdec : gstrtpdec.h Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h.diff?r1=1.6&r2=1.7 ====Begin Diffs==== Index: gstrtpdec.h =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- a/gstrtpdec.h 2 Mar 2004 22:53:06 -0000 1.6 +++ b/gstrtpdec.h 4 Mar 2004 19:44:38 -0000 1.7 @@ -113,9 +113,11 @@ int data_port, control_port; GstNumAddress remote_address; - in_port_t remote_data_port, remote_control_port; - GstNumAddress multicast_addr; + + in_port_t remote_data_port, remote_control_port; + gboolean multicast_mode; + gboolean default_authorized; GstAuthorizedAddrs authorized_senders; |
From: Ramon G. F. <ra...@pd...> - 2004-03-04 20:57:10
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Thu Mar 04 2004 12:50:52 PST Log message: Minor change Modified files: rtpdec : gstrtpdec.c rtpdec.h Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c.diff?r1=1.5&r2=1.6 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtpdec.h.diff?r1=1.3&r2=1.4 ====Begin Diffs==== Index: gstrtpdec.c =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- a/gstrtpdec.c 2 Mar 2004 22:53:06 -0000 1.5 +++ b/gstrtpdec.c 4 Mar 2004 20:50:40 -0000 1.6 @@ -299,11 +299,11 @@ gboolean sucess; g_assert(rtpdec != NULL); if (GST_STATE_PENDING(element) == GST_STATE_NULL) { - gst_rtpdec_close_conn(element); + gst_rtpdec_bye(element); return GST_STATE_SUCCESS; } if (GST_STATE(element) == GST_STATE_NULL && GST_STATE_PENDING(element) != GST_STATE_NULL) { - sucess = gst_rtpdec_open_conn(element); + sucess = gst_rtpdec_connect(element); return sucess ? GST_STATE_SUCCESS : GST_STATE_FAILURE; } Index: rtpdec.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtpdec.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- a/rtpdec.h 2 Mar 2004 22:53:06 -0000 1.3 +++ b/rtpdec.h 4 Mar 2004 20:50:40 -0000 1.4 @@ -10,7 +10,11 @@ void gst_rtpdec_dispatch_packet(GstRtpdec* rtpdec, guint size, gchar* data, struct sockaddr_in6* source, packet_type type); -void gst_rtpdec_set_mapping(GHashTable* mapping); +void gst_rtpdec_set_mapping(GstRtpdec* rtpdec, GHashTable* mapping); + +void gst_rtpdec_bye(GstRtpdec* rtpdec); +void gst_rtpdec_connect(GstRtpdec* rtpdec); guint32 createid(void); |
From: Ramon G. F. <ra...@pd...> - 2004-03-05 01:16:13
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Thu Mar 04 2004 17:08:12 PST Log message: Automatic path mtu adjusting Modified files: rtpdec : address.h gstrtpdec.c gstrtpdec.h rtpdec.h socket_fns.c Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/address.h.diff?r1=1.3&r2=1.4 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c.diff?r1=1.6&r2=1.7 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h.diff?r1=1.7&r2=1.8 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtpdec.h.diff?r1=1.4&r2=1.5 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/socket_fns.c.diff?r1=1.1&r2=1.2 ====Begin Diffs==== Index: address.h =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/address.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- a/address.h 2 Mar 2004 22:53:06 -0000 1.3 +++ b/address.h 5 Mar 2004 01:08:00 -0000 1.4 @@ -46,10 +46,17 @@ typedef struct _GstAuthorizedAddrs GstAuthorizedAddrs; -void resolve_address(const GstAddress* address, GstNumAddress* result); +void gst_addr_resolve_address(const GstAddress* address, GstNumAddress* result); -gboolean try_bind(int socket, const GstNumAddress* address, int port); +gboolean gst_addr_try_bind(int socket, const GstNumAddress* address, int port); -void try_send(int socket, GstNumAddress* remote, in_port_t port, const char* data, guint size); +void gst_addr_try_send(int socket, GstNumAddress* remote, in_port_t port, const char* data, guint size); + +void gst_addr_delete_address(GstAddress* addr); +void gst_addr_delete_num_address(GstNumAddress* addr); +void gst_addr_delete_authorized_addrs(GstAuthorizedAddrs* addr); #endif Index: gstrtpdec.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- a/gstrtpdec.c 4 Mar 2004 20:50:40 -0000 1.6 +++ b/gstrtpdec.c 5 Mar 2004 01:08:00 -0000 1.7 @@ -78,6 +78,9 @@ static gboolean rtpdec_init(GstPlugin* plugin); +static GObjectClass* parent_class = NULL; GType gst_rtpdec_get_type (void) { @@ -104,6 +107,7 @@ return rtpdec_type; } /* initialize the rtpdec's class */ static void gst_rtpdec_class_init (GstRtpdecClass *klass) @@ -124,6 +128,8 @@ gstelement_class->release_locks = gst_rtpdec_release_locks; gstelement_class->change_state = gst_rtpdec_change_state; gst_rtpdec_class->default_mapping = gst_rtpdec_create_av_mapping(); + parent_class = g_type_class_ref(GST_TYPE_ELEMENT); @@ -182,6 +188,24 @@ +gst_rtpdec_finalize(GstElement* element) +{ + if (element->mapping) { + gst_rtpdec_delete_mapping(element->mapping); + } + if (element->sender_list) { + gst_rtpdec_delete_sender_list(element->sender_list); + if (element->recv_list) { + gst_rtpdec_delete_recv_list(element->recv_list); + gst_addr_delete_num_address(element->remote_address); + gst_addr_delete_num_address(element->multicast_addr); + gst_addr_delete_authorized_addrs(element->authorized_senders); + parent_class->finalize(GST_ELEMENT(element)); +} +static void gst_rtpdec_main_loop(GstElement* element) guint data_size; Index: gstrtpdec.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h,v retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- a/gstrtpdec.h 4 Mar 2004 19:44:38 -0000 1.7 +++ b/gstrtpdec.h 5 Mar 2004 01:08:00 -0000 1.8 @@ -79,7 +79,7 @@ struct _GstRtpdec GstElement element; - /* mapping of payload byte => payload_desc */ + /* mapping of payload byte => GstStructure */ GHashTable* mapping; guint32 myid; /* Mapping of identifier -> sender_info */ @@ -123,11 +123,17 @@ guint mtu; - /* Write to pipe[0] for interrupting any blocking operation */ + /* Write to pipe[1] for interrupting any blocking operation */ int pipe[2]; /* Pipe for communicating with the thread that sends reports */ int report_thread_pipe[2]; + /* Possible messages sent to that thread */ + /* The expected schedule for sending the next packet changed */ +#define SCHED_NEXT_PACKET_CHANGED 'S' + /* The network has told us that our packets are too large */ +#define PATH_MTU_CHANGED 'P' }; struct _GstRtpdecClass Index: rtpdec.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtpdec.h,v retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- a/rtpdec.h 4 Mar 2004 20:50:40 -0000 1.4 +++ b/rtpdec.h 5 Mar 2004 01:08:00 -0000 1.5 @@ -19,4 +19,11 @@ guint32 createid(void); GString* make_cname(void); +void gst_rtpdec_delete_mapping(GHashTable* mapping); +void gst_rtpdec_delete_sender_list(GHashTable* sender_list); +void gst_rtpdec_delete_recv_list(GHashTable* recv_list); Index: socket_fns.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/socket_fns.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- a/socket_fns.c 27 Feb 2004 05:24:52 -0000 1.1 +++ b/socket_fns.c 5 Mar 2004 01:08:00 -0000 1.2 @@ -1,8 +1,86 @@ +#include <sys/poll.h> #include "socket_fns.h" +static void handle_error_message(GstRtpdec* dec, int fd); gboolean wait_for_data(GstRtpdec* element, gunit* data_size, gchar** data, struct sockaddr_in6 *peer, packet_type* type) - + struct pollfd fds[3] = { + {.fd = element->control_socket, + .events = POLLIN | POLLERR, + .revents = 0}, + {.fd = element->data_socket, + {.fd = element->pipe, + .events = POLLIN, + .revents = 0}}; + gboolean try_again; + do { + poll(&fds, 3, -1); + if (fd[2].revents & POLLIN) { + *data_size = 0; + *data = NULL; + return FALSE; + } else if ((fd[0].revents & POLLIN) || (fd[1].revents & POLLIN)) { + int active_fd; + if (fd[0].revents & POLLIN) { + active_fd = element->control_socket; + *type = control_packet; + } else { + active_fd = element->data_socket; + *type = data_packet; + } + ioctl(active_fd, FIONREAD, data_size); + *data = g_malloc(*data_size); + recvfrom(active_fd, data, *data_size, 0, + peer, sizeof(struct sockaddr_in6)); + try_again = FALSE; + } else if ((fd[0].revents & POLLERR) || (fd[1].revents & POLLERR)) { + if (fd[0].revents & POLLERR) { + handle_error_message(element, active_fd); + try_again = TRUE; + } + } while(try_again); +static void handle_error_message(GstRtpdec* element, int fd) + struct sockaddr_in6 peer; + struct sock_extended_err* sock_error; + /* FIXME: reliable way of knowning size of the buffer bellow?? */ + char buf[CMSG_SPACE(sizeof sock_extended_err) + sizeof(struct sockaddr_in6) + 256]; + struct msghdr msg = { + .msg_name = &peer, + .msg_name_len = sizeof(struct sockaddr_in6), + .msg_iov = NULL, + .msg_iovlen = 0, + .msg_control = buf, + .msg_control_len = sizeof(buf), + .msg_flags = MSG_ERRQUEUE}; + struct cmsghdr* cmsg; + recvmsg(fd, &msg, MSG_ERRQUEUE); + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR) { + sock_error = (struct sock_extended_err*) CMSG_DATA(cmsg); + if (sock_error->ee_errno == EMSGSIZE) { + set_mtu(element, sock_error->ee_info); +static void set_mtu(GstRtpdec* element, unsigned int mtu) + char m = PATH_MTU_CHANGED; + element->mtu = mtu; + write(element->report_thread_pipe[1], &m, 1); |
From: Ramon G. F. <ra...@pd...> - 2004-03-07 13:36:42
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Sun Mar 07 2004 05:28:46 PST Log message: weekend work Modified files: rtpdec : address.c address.h socket_fns.c socket_fns.h Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/address.c.diff?r1=1.1&r2=1.2 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/address.h.diff?r1=1.4&r2=1.5 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/socket_fns.c.diff?r1=1.2&r2=1.3 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/socket_fns.h.diff?r1=1.2&r2=1.3 ====Begin Diffs==== Index: address.c =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/address.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- a/address.c 27 Feb 2004 04:47:28 -0000 1.1 +++ b/address.c 7 Mar 2004 13:28:34 -0000 1.2 @@ -5,18 +5,6 @@ static void gst_address_free(gpointer); -static gpointer gst_address_list_copy(gpointer); - -static void gst_address_list_free(gpointer); -static gpointer gst_addr_port_copy(gpointer); -static void gst_addr_port_free(gpointer); -static gpointer gst_addr_port_list_copy(gpointer); -static void gst_addr_port_list_free(gpointer); static void resolve_name(const gchar* name, GstNumAddress* result); GType @@ -53,117 +41,16 @@ g_free(ptr); } -GType -gst_address_list_get_type(void) { - static GType type = 0; - if (type == 0) { - type = g_boxed_type_register_static("GstAddressList", - gst_address_list_copy, - gst_address_list_free); - } - return type; -} -static gpointer -gst_address_list_copy(gpointer src) -{ - GList* src_list = (GList*) src; - GList* dest_list = NULL; - GList* list_node = src_list; - while (list_node != NULL) { - dest_list = g_list_append(dest_list, gst_address_copy(list_node->data)); - list_node = g_list_next(list_node); - return (gpointer) dest_list; -static void -gst_address_list_free(gpointer ptr) - GList* ptr_list = (GList*) ptr; - GList* list_node = ptr_list; - gst_address_free(list_node->data); - list_node = g_list_remove_link(list_node, list_node); -static gpointer -gst_addr_port_copy(gpointer src) - GstAddrPort* addr_src = (GstAddrPort*) src; - GstAddrPort* addr_result; - addr_result = g_new0(GstAddrPort, 1); - *addr_result = *addr_src; - if (addr_src->addr.type == NAME) { - addr_result->addr.addr.name = g_strdup(addr_src->addr.addr.name); - return (gpointer) addr_result; -static void -gst_addr_port_free(gpointer ptr) - GstAddrPort* addr_ptr = (GstAddrPort*) ptr; - if (addr_ptr->addr.type == NAME) { - g_free(addr_ptr->addr.addr.name); - g_free(ptr); -gst_addr_port_get_type(void) - type = g_boxed_type_register_static("GstAddrPort", - gst_addr_port_copy, - gst_addr_port_free); -GType -gst_addr_port_list_get_type(void) - type = g_boxed_type_register_static("GstAddrPortList", - gst_addr_port_list_copy, - gst_addr_port_list_free); -gst_addr_port_list_copy(gpointer src) - dest_list = g_list_append(dest_list, gst_addr_port_copy(list_node->data)); -gst_addr_port_list_free(gpointer ptr) +void +gst_addr_free_num_address(GstNumAddress* addr) { - gst_addr_port_free(list_node->data); + if (addr->alternatives) { + g_free(addr->alternatives); } void -resolve_address(const GstAddress* address, GstNumAddress* result) +gst_addr_resolve_address(const GstAddress* address, GstNumAddress* result) if (result->alternatives != NULL) { g_free(result->alternatives); @@ -186,7 +73,6 @@ static void resolve_name(const gchar* name, GstNumAddress* result) @@ -252,3 +138,28 @@ break; + +gboolean +gst_addr_allowed(GstAuthorizedAddrs* acls, struct sockaddr_in6* peer) +{ + GstAuthorizedAddr* acl_entry; + GstNumAddr* addr; + struct in6_addr* addr_alt; + unsigned int i, j; + for (i = 0; i < acls->authorized_addrs->len; i ++) { + acl_entry = ((GstAuthorizedAddr *) acls->authorized_addrs->data)[i]; + if (peer->sin6_port < acl_entry->low || + peer->sin6_port > acl_entry->high) + continue; + addr = &acl_entry->addr; + for (j = 0; j < addr->alternatives->len; j++) { + addr_alt = ((struct in6_addr*) + addr->alternatives->data)[j]; + if (memcpy(addr_alt, peer->sin6_addr, sizeof(struct sockaddr_in6))) { + return TRUE; + } + } + } + return FALSE; +} Index: address.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/address.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- a/address.h 5 Mar 2004 01:08:00 -0000 1.4 +++ b/address.h 7 Mar 2004 13:28:34 -0000 1.5 @@ -46,9 +46,12 @@ typedef struct _GstAuthorizedAddrs GstAuthorizedAddrs; +void gst_addr_free_num_address(GstNumAddress* addr); void gst_addr_resolve_address(const GstAddress* address, GstNumAddress* result); +gboolean gst_addr_in_list(const GstAddress* address, struct in6_addr addr); -gboolean gst_addr_try_bind(int socket, const GstNumAddress* address, int port); +gboolean gst_addr_try_bind(int socket, const GstNumAddress* address, in_port_t port); void gst_addr_try_send(int socket, GstNumAddress* remote, in_port_t port, const char* data, guint size); Index: socket_fns.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/socket_fns.c,v retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- a/socket_fns.c 5 Mar 2004 01:08:00 -0000 1.2 +++ b/socket_fns.c 7 Mar 2004 13:28:34 -0000 1.3 @@ -84,3 +84,85 @@ element->mtu = mtu; write(element->report_thread_pipe[1], &m, 1); +authorized_packet(GstRtpdec* element, struct sockaddr_in6* addr, packet_type* type) + if (element->default_authorized) { + if (element->multicast_mode) { + return TRUE; + } else { + return gst_addr_in_list(element->remote_address); + } else { + return gst_addr_allowed(element->authorized_senders, addr); +gst_rtpdec_open_conn(GstElement* element) + int error; + gboolean bound; + bound = FALSE; + if (element->data_port < 0 && element->control_port < 0) { + bound = try_bind(element, 5004, &element->data_socket); + if (bound) { + bound = try_bind(element, 5005, &element->control_socket); + if (!bound) { + close(element->data_socket); + } + if (!bound) { + bound = try_bind_both_random(element); + if (!bound) + goto error; + } else if (element->data_port > 0 && element->control_port < 0) { + bound = try_bind(element, element->data_port, &element->data_socket); + bound = try_bind(element, element->data_port + 1, &element->control_socket); + bound = try_bind_random(element, &element->control_socket); + } else { + bound = try_bind_both_random(element); + } + error: + if (element->control_socket >= 0) { + close(element->control_socket); + if (element->data_socket >= 0) { + close(element->data_socket); + return FALSE; +gboolen +try_bind_one(GstRtpdec* element, in_port_t port, int* socket) + struct sockaddr_in6 addr; + int i; + gboolean result; + *socket = socket(AF_INET6, SOCK_DGRAM, 0); + result = gst_addr_try_bind(*socket, element->local_address, port); + if (!result) { + close(*socket); + *socket = -1; + return result; +static gboolean +try_bind_random(GstRtpdec* element, int* socket) + result = gst_addr_try_bind(*socket, element->local_address, ); Index: socket_fns.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/socket_fns.h,v --- a/socket_fns.h 2 Mar 2004 06:31:12 -0000 1.2 +++ b/socket_fns.h 7 Mar 2004 13:28:34 -0000 1.3 @@ -9,20 +9,6 @@ gboolean authorized_packet(GstRtpdec* element, struct sockaddr_in6* addr, packet_type* type); -void gst_rtpdec_set_data_port(guint port); -void gst_rtpdec_set_ctl_port(guint port); -void gst_rtpdec_set_local_addr(GstAddress* addr); -void gst_rtpdec_set_remote_addr(GstAddress* addr); -void gst_rtpdec_set_remote_data_port(guint port); -void gst_rtpdec_set_remote_ctl_port(guint port); -void gst_rtpdec_set_multicast_addr(GstAddress* addr); gboolean gst_rtpdec_open_conn(GstElement* element); void gst_rtpdec_close_conn(GstElement* element); |
From: Ramon G. F. <ra...@pd...> - 2004-03-08 23:44:51
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Mon Mar 08 2004 15:36:04 PST Log message: Completed somewhat socket_fns; corrected gstrtpdec Modified files: rtpdec : address.c address.h gstrtpdec.c rtpdec.h socket_fns.c Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/address.c.diff?r1=1.2&r2=1.3 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/address.h.diff?r1=1.5&r2=1.6 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c.diff?r1=1.7&r2=1.8 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtpdec.h.diff?r1=1.5&r2=1.6 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/socket_fns.c.diff?r1=1.3&r2=1.4 ====Begin Diffs==== Index: address.c =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/address.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- a/address.c 7 Mar 2004 13:28:34 -0000 1.2 +++ b/address.c 8 Mar 2004 23:35:52 -0000 1.3 @@ -104,15 +104,15 @@ } gboolean -try_bind(int socket, const GstNumAddress* address, int port) +gst_addr_try_bind(int socket, const GstNumAddress* address, in_port_t port) { int error; int i; struct in6_addr addr; - g_assert(address->num_alternatives > 0); - for (i = 0; i < address->num_alternatives; i++) { - addr = address->alternatives[i]; - addr.sin_port = port; + g_assert(address->len > 0); + for (i = 0; i < address->len; i++) { + addr = g_array_index(address, struct in6_addr, i); + addr.sin6_port = port; error = bind(socket, &addr, sizeof(struct in6_addr)); if (error == 0) { break; @@ -121,6 +121,25 @@ return (error != 0); +gboolean +gst_addr_try_connect(int socket, const GstNumAddress* address, in_port_t port) +{ + int error; + int i; + struct in6_adr addr; + g_assert(addess->len > 0); + error = connect(socket, &addr, sizeof(struct in6_addr)); + if (error == 0) { + break; + } + } + return (error != 0); + +} void try_send(int socket, GstNumAddressPort* remote, const char* data, guint size) @@ -148,7 +167,7 @@ struct in6_addr* addr_alt; unsigned int i, j; for (i = 0; i < acls->authorized_addrs->len; i ++) { - acl_entry = ((GstAuthorizedAddr *) acls->authorized_addrs->data)[i]; + acl_entry = g_array_index(acls->authorized_addrs, GstAuthorizedAddr, i); if (peer->sin6_port < acl_entry->low || peer->sin6_port > acl_entry->high) continue; Index: address.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/address.h,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- a/address.h 7 Mar 2004 13:28:34 -0000 1.5 +++ b/address.h 8 Mar 2004 23:35:52 -0000 1.6 @@ -53,6 +53,8 @@ gboolean gst_addr_try_bind(int socket, const GstNumAddress* address, in_port_t port); +gboolean gst_addr_try_connect(int socket, const GstNumAddress* address, in_port_t port); void gst_addr_try_send(int socket, GstNumAddress* remote, in_port_t port, const char* data, guint size); Index: gstrtpdec.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- a/gstrtpdec.c 5 Mar 2004 01:08:00 -0000 1.7 +++ b/gstrtpdec.c 8 Mar 2004 23:35:52 -0000 1.8 @@ -144,10 +144,6 @@ rtpdec->clock = NULL; gst_element_set_loop_function(element, gst_rtpdec_main_loop); rtpdec->myid = create_id(); - g_thread_create(gst_rtpdec_send_report_thread, element, TRUE, &error); - if (error != NULL) { - g_warning("Cannot perform sender reports"); - } rtpdec->mapping = NULL; rtpdec->sender_list = g_hash_table_new(g_int_hash, g_int_equal); @@ -322,13 +318,27 @@ GstRtpdec* rtpdec = GST_RTPDEC(element); gboolean sucess; g_assert(rtpdec != NULL); - if (GST_STATE_PENDING(element) == GST_STATE_NULL) { - gst_rtpdec_bye(element); - return GST_STATE_SUCCESS; - if (GST_STATE(element) == GST_STATE_NULL && GST_STATE_PENDING(element) != GST_STATE_NULL) { - sucess = gst_rtpdec_connect(element); + guint8 current_state, next_state; + current_state = GST_STATE(element); + next_state = GST_STATE_PENDING(element); + if (current_state == GST_STATE_NULL && pending_state == GST_STATE_READY) { + sucess = gst_rtpdec_open_conn(element); return sucess ? GST_STATE_SUCCESS : GST_STATE_FAILURE; + } else if (current_state == GST_STATE_READY && pending_state == GST_STATE_PAUSED) { + gst_rtpdec_connect(element); + } else if (current_state == GST_STATE_PAUSED && pending_state == GST_STATE_PLAYING) { + return GST_STATE_SUCCESS; + } else if (current_state == GST_STATE_PLAYING && pending_state == GST_STATE_PAUSED) { + } else if (current_state == GST_STATE_PAUSED && pending_state == GST_STATE_READY) { + gst_rtpdec_disconnect(element); + return GST_STATE_SUCESS; + } else if (current_state == GST_STATE_READY && pending_state == GST_STATE_NULL) { + gst_rtpdec_close_conn(element); + } else { + g_warning("gstrtpdec: Invalid state change"); + return GST_STATE_FAILURE; } Index: rtpdec.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtpdec.h,v --- a/rtpdec.h 5 Mar 2004 01:08:00 -0000 1.5 +++ b/rtpdec.h 8 Mar 2004 23:35:52 -0000 1.6 @@ -12,7 +12,7 @@ void gst_rtpdec_set_mapping(GstRtpdec* rtpdec, GHashTable* mapping); -void gst_rtpdec_bye(GstRtpdec* rtpdec); +void gst_rtpdec_disconnect(GstRtpdec* rtpdec); void gst_rtpdec_connect(GstRtpdec* rtpdec); Index: socket_fns.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/socket_fns.c,v retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- a/socket_fns.c 7 Mar 2004 13:28:34 -0000 1.3 +++ b/socket_fns.c 8 Mar 2004 23:35:52 -0000 1.4 @@ -106,7 +106,7 @@ gboolean bound; bound = FALSE; - if (element->data_port < 0 && element->control_port < 0) { + if (element->data_port <= 0 && element->control_port <= 0) { bound = try_bind(element, 5004, &element->data_socket); if (bound) { bound = try_bind(element, 5005, &element->control_socket); @@ -119,7 +119,7 @@ } if (!bound) goto error; - } else if (element->data_port > 0 && element->control_port < 0) { + } else if (element->data_port > 0 && element->control_port <= 0) { bound = try_bind(element, element->data_port, &element->data_socket); @@ -129,8 +129,27 @@ } else { - bound = try_bind_both_random(element); + bound = try_bind(element, element->data_port, &element->data_socket); + if (!bound) + goto error; + bound = try_bind(element, element->control_port, &element->control_socket); + if (element->multicas_mode) { + sucess = subscribe_multicast(element->data_socket, element->multicast_addr); + if (!sucess) + sucess = subscribe_multicast(element->control_socket, element->multicast_addr); + sucess = gst_addr_try_connect(element->data_socket, element->remote_addr, element->remote_data_port); + if (!sucess) + sucess = gst_addr_try_connect(element->control_socket, element->remote_addr, element->remote_control_port); + return TRUE; error: if (element->control_socket >= 0) { close(element->control_socket); @@ -143,7 +162,7 @@ gboolen -try_bind_one(GstRtpdec* element, in_port_t port, int* socket) +try_bind(GstRtpdec* element, in_port_t port, int* socket) struct sockaddr_in6 addr; @@ -164,5 +183,37 @@ gboolean result; - result = gst_addr_try_bind(*socket, element->local_address, ); + result = gst_addr_try_bind(*socket, element->local_address, 0); +static gboolean +try_bind_both_random(element) + gboolean sucess_1, sucess_2; + sucess_1 = try_bind_random(element, &element->data_socket); + if (!sucess_1) + return FALSE; + sucess_2 = try_bind_random(element, &element->control_socket); + return success_2; +subscribe_multicast(GstRtpdec* element, int fd, GstNumAddress multicast_addr) + unsigned int i; + struct in6_addr* the_addr; + struct ipv6_mreq ipv6_mreq; + for (i = 0; i < multicast_addr.alternatives->len; i++) { + the_addr = g_array_index(multicast_addr.alternatives, struct in6_addr, i); + ipv6_mreq.ipv6mr_multiaddr = *the_addr; + /* FIXME: the user should be able to choose an interface */ + ipv6_mreq.ipv6mr_interface = 0; + error = setsockopt(fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &ipv6_mreq); + return error == 0; |
From: Ramon G. F. <ra...@pd...> - 2004-03-09 17:38:18
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Tue Mar 09 2004 09:29:00 PST Log message: Impl close conn Modified files: rtpdec : socket_fns.c socket_fns.h Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/socket_fns.c.diff?r1=1.4&r2=1.5 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/socket_fns.h.diff?r1=1.3&r2=1.4 ====Begin Diffs==== Index: socket_fns.c =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/socket_fns.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- a/socket_fns.c 8 Mar 2004 23:35:52 -0000 1.4 +++ b/socket_fns.c 9 Mar 2004 17:28:48 -0000 1.5 @@ -217,3 +217,9 @@ return error == 0; } +void gst_rtpdec_close_conn(GstRtpdec* element) +{ + close(element->data_socket); + close(element->control_socket); +} + Index: socket_fns.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/socket_fns.h,v retrieving revision 1.3 diff -u -d -r1.3 -r1.4 --- a/socket_fns.h 7 Mar 2004 13:28:34 -0000 1.3 +++ b/socket_fns.h 9 Mar 2004 17:28:48 -0000 1.4 @@ -4,14 +4,14 @@ #include "gstrtpdec.h" #include "packet_type.h" -gboolean wait_for_data(GstRtpdec* element, +gboolean wait_for_data(const GstRtpdec* element, guint* data_size, gchar** data, struct sockaddr_in6 *peer, packet_type* type); -gboolean authorized_packet(GstRtpdec* element, struct sockaddr_in6* addr, packet_type* type); +gboolean authorized_packet(const GstRtpdec* element, struct sockaddr_in6* addr, packet_type* type); -gboolean gst_rtpdec_open_conn(GstElement* element); +gboolean gst_rtpdec_open_conn(GstRtpdec* element); -void gst_rtpdec_close_conn(GstElement* element); +void gst_rtpdec_close_conn(GstRtpdec* element); #endif |
From: Ramon G. F. <ra...@pd...> - 2004-03-18 12:05:45
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Thu Mar 18 2004 04:05:43 PST Log message: Added indent cmd Added files: rtpdec : do_indent Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/do_indent?rev=1.1&content-type=text/vnd.viewcvs-markup ====Begin Diffs==== --- NEW FILE: do_indent --- indent -br -bad -cbi0 -cli2 -bls -l80 -ut -ce -nlp -ci4 -hnl |
From: Ramon G. F. <ra...@pd...> - 2004-03-20 23:33:44
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Sat Mar 20 2004 15:33:40 PST Log message: Some compilation fixes; indent Modified files: rtpdec : Makefile address.c address.h do_indent gstrtpdec.c gstrtpdec.h gstrtphandler.h ntohll.h packet_type.h rtp_packet.h rtp_report.c rtp_report.h rtpdec.c rtpdec.h socket_fns.c socket_fns.h Removed files: rtpdec : rtp_ctl_event.h Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/Makefile.diff?r1=1.1&r2=1.2 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/address.c.diff?r1=1.3&r2=1.4 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/address.h.diff?r1=1.6&r2=1.7 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/do_indent.diff?r1=1.1&r2=1.2 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c.diff?r1=1.9&r2=1.10 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h.diff?r1=1.8&r2=1.9 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtphandler.h.diff?r1=1.1&r2=1.2 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/ntohll.h.diff?r1=1.1&r2=1.2 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/packet_type.h.diff?r1=1.2&r2=1.3 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_ctl_event.h http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_packet.h.diff?r1=1.1&r2=1.2 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_report.c.diff?r1=1.4&r2=1.5 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_report.h.diff?r1=1.2&r2=1.3 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtpdec.c.diff?r1=1.4&r2=1.5 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtpdec.h.diff?r1=1.6&r2=1.7 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/socket_fns.c.diff?r1=1.5&r2=1.6 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/socket_fns.h.diff?r1=1.5&r2=1.6 ====Begin Diffs==== Index: Makefile =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/Makefile,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- a/Makefile 17 Mar 2004 23:54:07 -0000 1.1 +++ b/Makefile 20 Mar 2004 23:33:28 -0000 1.2 @@ -1,6 +1,6 @@ CFLAGS=$(shell pkg-config --cflags gstreamer-0.7) -DGST_PACKAGE='"GStreamer"' -DGST_ORIGIN='"http://gstreamer.net"' -DVERSION='"0.0"' -check: gstrtpdec.o rtpdec.o rtp_report.o +check: gstrtpdec.o rtpdec.o rtp_report.o socket_fns.o gstrtpdec.o: gstrtpdec.c libtool --mode=compile gcc $(CFLAGS) -c gstrtpdec.c @@ -9,4 +9,7 @@ libtool --mode=compile gcc $(CFLAGS) -c rtpdec.c rtp_report.o: rtp_report.c - libtool --mode=compile gcc $(CFLAGS) -c rtp_report.c \ No newline at end of file + libtool --mode=compile gcc $(CFLAGS) -c rtp_report.c + +socket_fns.o: socket_fns.c + libtool --mode=compile gcc $(CFLAGS) -c socket_fns.c Index: address.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/address.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- a/address.c 8 Mar 2004 23:35:52 -0000 1.3 +++ b/address.c 20 Mar 2004 23:33:28 -0000 1.4 @@ -1,119 +1,127 @@ #include "address.h" #include <netdb.h> -static gpointer gst_address_copy(gpointer); +static gpointer gst_address_copy (gpointer); -static void gst_address_free(gpointer); +static void gst_address_free (gpointer); -static void resolve_name(const gchar* name, GstNumAddress* result); +static void resolve_name (const gchar * name, GstNumAddress * result); GType -gst_address_get_type(void) { +gst_address_get_type (void) +{ static GType address_type = 0; if (address_type == 0) { - address_type = g_boxed_type_register_static("GstAddress", - gst_address_copy, - gst_address_free); + address_type = g_boxed_type_register_static ("GstAddress", + gst_address_copy, gst_address_free); } return address_type; } -static gpointer -gst_address_copy(gpointer src) +static gpointer +gst_address_copy (gpointer src) { - GstAddress* addr_src = (GstAddress*) src; - GstAddress* addr_result; - addr_result = g_new0(GstAddress, 1); + GstAddress *addr_src = (GstAddress *) src; + GstAddress *addr_result; + addr_result = g_new0 (GstAddress, 1); *addr_result = *addr_src; if (addr_src->type == NAME) { - addr_result->addr.name = g_strdup(addr_src->addr.name); + addr_result->addr.name = g_strdup (addr_src->addr.name); return (gpointer) addr_result; -static void -gst_address_free(gpointer ptr) +static void +gst_address_free (gpointer ptr) - GstAddress* addr_ptr = (GstAddress*) ptr; - if (addr_ptr->type == NAME) { - g_free(addr_ptr->addr.name); + GstAddress *addr_ptr = (GstAddress *) ptr; + if (addr_ptr->type == NAME) { + g_free (addr_ptr->addr.name); - g_free(ptr); + g_free (ptr); void -gst_addr_free_num_address(GstNumAddress* addr) +gst_addr_free_num_address (GstNumAddress * addr) if (addr->alternatives) { - g_free(addr->alternatives); + g_free (addr->alternatives); -void -gst_addr_resolve_address(const GstAddress* address, GstNumAddress* result) +void +gst_addr_resolve_address (const GstAddress * address, GstNumAddress * result) if (result->alternatives != NULL) { - g_free(result->alternatives); + g_free (result->alternatives); - result->num_alternatives = 0 - result->alternatives = NULL; + result->num_alternatives = 0 result->alternatives = NULL; switch (address->type) { - case IPV4: - result->num_alternatives = 1; - result->alternatives = g_new(struct in6_addr, 1); - map_ipv4_to_ipv6(address->addr.ipv4_address, result->alternatives[0]); - break; - case IPV6: - result->alternatives[0] = address->addr.ipv6_address; - case NAME: - resolve_name(address->addr.name, result); - + case IPV4: + result->num_alternatives = 1; + result->alternatives = g_new (struct in6_addr, 1); + map_ipv4_to_ipv6 (address->addr.ipv4_address, result->alternatives[0]); + break; + case IPV6: + result->alternatives[0] = address->addr.ipv6_address; + case NAME: + resolve_name (address->addr.name, result); static void -resolve_name(const gchar* name, GstNumAddress* result) +resolve_name (const gchar * name, GstNumAddress * result) int error; - struct addrinfo* result; - struct addrinfo* link; - error = getaddrinfo(name, NULL, NULL, &result); - if (error != 0) + struct addrinfo *result; + struct addrinfo *link; + error = getaddrinfo (name, NULL, NULL, &result); + if (error != 0) return; result->num_alternatives = 0; link = result; - while(link != NULL) { + while (link != NULL) { if (link->ai_family == AF_INET || link->ai_family == AF_INET6) { result->num_alternatives++; } link = link->ai_next; - result->alternatives = g_new0(struct in6_addr, result->num_alternatives); + result->alternatives = g_new0 (struct in6_addr, result->num_alternatives); alternative = result->alternatives; if (link->ai_protocol == AF_INET || link->ai_family == AF_INET6) { *alternative = ((struct sockaddr_in6 *) link->ai_addr)->sin6_addr; alternative++; - freeaddrinfo(result); + freeaddrinfo (result); -gboolean -gst_addr_try_bind(int socket, const GstNumAddress* address, in_port_t port) +gboolean +gst_addr_try_bind (int socket, const GstNumAddress * address, in_port_t port) int i; struct in6_addr addr; - g_assert(address->len > 0); + g_assert (address->len > 0); for (i = 0; i < address->len; i++) { - addr = g_array_index(address, struct in6_addr, i); + addr = g_array_index (address, struct in6_addr, i); addr.sin6_port = port; - error = bind(socket, &addr, sizeof(struct in6_addr)); + error = bind (socket, &addr, sizeof (struct in6_addr)); if (error == 0) { break; @@ -122,16 +130,18 @@ gboolean -gst_addr_try_connect(int socket, const GstNumAddress* address, in_port_t port) +gst_addr_try_connect (int socket, const GstNumAddress * address, in_port_t port) struct in6_adr addr; - g_assert(addess->len > 0); + g_assert (addess->len > 0); - error = connect(socket, &addr, sizeof(struct in6_addr)); + error = connect (socket, &addr, sizeof (struct in6_addr)); @@ -141,17 +151,18 @@ -try_send(int socket, GstNumAddressPort* remote, const char* data, guint size) +try_send (int socket, GstNumAddressPort * remote, const char *data, guint size) struct sockaddr_in6 peer; guint i; gboolean sucess; peer.sin6_port = remote->port; peer.sin6_flowinfo = 0; peer.sin6_scope_id = 0; for (i = 0; i < remote->address.num_alternatives; i++) { peer.sin6_addr = remote->address.alternatives[i]; - error = sendto(socket, data, size, 0, &peer, sizeof(sockaddr_in6)); + error = sendto (socket, data, size, 0, &peer, sizeof (sockaddr_in6)); sucess = error >= 0; if (sucess) @@ -160,25 +171,25 @@ -gst_addr_allowed(GstAuthorizedAddrs* acls, struct sockaddr_in6* peer) +gst_addr_allowed (GstAuthorizedAddrs * acls, struct sockaddr_in6 *peer) - GstAuthorizedAddr* acl_entry; - GstNumAddr* addr; - struct in6_addr* addr_alt; - unsigned int i, j; - for (i = 0; i < acls->authorized_addrs->len; i ++) { - acl_entry = g_array_index(acls->authorized_addrs, GstAuthorizedAddr, i); - if (peer->sin6_port < acl_entry->low || - peer->sin6_port > acl_entry->high) - continue; - addr = &acl_entry->addr; - for (j = 0; j < addr->alternatives->len; j++) { - addr_alt = ((struct in6_addr*) - addr->alternatives->data)[j]; - if (memcpy(addr_alt, peer->sin6_addr, sizeof(struct sockaddr_in6))) { - return TRUE; - } - } + GstAuthorizedAddr *acl_entry; + GstNumAddr *addr; + struct in6_addr *addr_alt; + unsigned int i, j; + for (i = 0; i < acls->authorized_addrs->len; i++) { + acl_entry = g_array_index (acls->authorized_addrs, GstAuthorizedAddr, i); + if (peer->sin6_port < acl_entry->low || peer->sin6_port > acl_entry->high) + continue; + addr = &acl_entry->addr; + for (j = 0; j < addr->alternatives->len; j++) { + addr_alt = ((struct in6_addr *) + addr->alternatives->data)[j]; + if (memcpy (addr_alt, peer->sin6_addr, sizeof (struct sockaddr_in6))) { + return TRUE; + } - return FALSE; + } + return FALSE; Index: address.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/address.h,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- a/address.h 8 Mar 2004 23:35:52 -0000 1.6 +++ b/address.h 20 Mar 2004 23:33:28 -0000 1.7 @@ -4,18 +4,21 @@ #include <glib-object.h> #include <netinet/in.h> -struct _GstAddress { - enum {ADDR_IPV4, ADDR_IPV6, ADDR_NAME} type; - union addr_fmt { +struct _GstAddress + enum + { ADDR_IPV4, ADDR_IPV6, ADDR_NAME } type; + union addr_fmt + { struct in_addr ipv4_address; struct in6_addr ipv6_address; - char* name; + char *name; } addr; }; typedef struct _GstAddress GstAddress; -GType gst_address_get_type(); +GType gst_address_get_type (); #define GST_TYPE_ADDRESS (gst_address_get_type()) @@ -24,44 +27,52 @@ that can be accesses throught any of these addresses. It is the result of a name resolution that returns a list of addresses */ -struct _GstNumAddress { - GArray* alternatives; /* Array of struct in6_addr */ +struct _GstNumAddress + GArray *alternatives; /* Array of struct in6_addr */ typedef struct _GstNumAddress GstNumAddress; -GstNumAddress gst_addr_any(); +GstNumAddress gst_addr_any (); -struct _GstAuthorizedAddr { +struct _GstAuthorizedAddr GstNumAddress addr; in_port_t low, high; typedef struct _GstAuthorizedAddr GstAuthorizedAddr; -struct _GstAuthorizedAddrs { - GArray* authorized_addrs; +struct _GstAuthorizedAddrs + GArray *authorized_addrs; typedef struct _GstAuthorizedAddrs GstAuthorizedAddrs; -void gst_addr_free_num_address(GstNumAddress* addr); +void gst_addr_free_num_address (GstNumAddress * addr); -void gst_addr_resolve_address(const GstAddress* address, GstNumAddress* result); -gboolean gst_addr_in_list(const GstAddress* address, struct in6_addr addr); +void gst_addr_resolve_address (const GstAddress * address, + GstNumAddress * result); -gboolean gst_addr_try_bind(int socket, const GstNumAddress* address, in_port_t port); +gboolean gst_addr_in_list (const GstAddress * address, struct in6_addr *addr); -gboolean gst_addr_try_connect(int socket, const GstNumAddress* address, in_port_t port); +gboolean gst_addr_try_bind (int socket, const GstNumAddress * address, + in_port_t port); -void gst_addr_try_send(int socket, GstNumAddress* remote, in_port_t port, const char* data, guint size); +gboolean gst_addr_try_connect (int socket, const GstNumAddress * address, +void gst_addr_try_send (int socket, GstNumAddress * remote, in_port_t port, + const char *data, guint size); -void gst_addr_delete_address(GstAddress* addr); -void gst_addr_delete_num_address(GstNumAddress* addr); +void gst_addr_delete_address (GstAddress * addr); -void gst_addr_delete_authorized_addrs(GstAuthorizedAddrs* addr); +void gst_addr_delete_num_address (GstNumAddress * addr); +void gst_addr_delete_authorized_addrs (GstAuthorizedAddrs * addr); #endif Index: do_indent RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/do_indent,v --- a/do_indent 18 Mar 2004 12:05:31 -0000 1.1 +++ b/do_indent 20 Mar 2004 23:33:28 -0000 1.2 @@ -1 +1 @@ -indent -br -bad -cbi0 -cli2 -bls -l80 -ut -ce -nlp -ci4 -hnl +indent -br -bad -cbi0 -cli2 -bls -l80 -ut -ce -nlp -ci4 -hnl *.[ch] Index: gstrtpdec.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- a/gstrtpdec.c 17 Mar 2004 23:54:07 -0000 1.9 +++ b/gstrtpdec.c 20 Mar 2004 23:33:28 -0000 1.10 @@ -26,18 +26,20 @@ "Rtp decoder", "0.0", "Ramon Garcia Fernandez. " - "Sponsored by CSOA Laboratorio 3 http://laboratorio3.net", + "Sponsored by CSOA Laboratorio 3 http://laboratorio3.net", "(C) 2002, 2003" /* Filter signals and args */ -enum { +enum /* FILL ME */ LAST_SIGNAL ARG_0, ARG_LOCAL_DATA_PORT, ARG_LOCAL_CONTROL_PORT, @@ -52,33 +54,32 @@ -static GstStaticPadTemplate gst_rtpdec_src_template = -GST_STATIC_PAD_TEMPLATE( - "src_%02d", - GST_PAD_SRC, - GST_PAD_SOMETIMES, - GST_STATIC_CAPS_ANY); +GstStaticPadTemplate gst_rtpdec_src_template = +GST_STATIC_PAD_TEMPLATE ("src_%02d", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS_ANY); -static void gst_rtpdec_class_init(GstRtpdecClass *klass); +static void gst_rtpdec_class_init (GstRtpdecClass * klass); -static void gst_rtpdec_init (GstRtpdec *filter); +static void gst_rtpdec_init (GstRtpdec * filter); -static void gst_rtpdec_set_property(GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec); -static void gst_rtpdec_get_property(GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec); -static void gst_rtpdec_main_loop(GstElement* element); +static void gst_rtpdec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_rtpdec_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_rtpdec_main_loop (GstElement * element); -static void gst_rtpdec_set_clock(GstElement* element, GstClock* clock); +static void gst_rtpdec_set_clock (GstElement * element, GstClock * clock); -static gboolean gst_rtpdec_release_locks(GstElement* element); +static gboolean gst_rtpdec_release_locks (GstElement * element); -static GstElementStateReturn gst_rtpdec_change_state(GstElement* element); +static GstElementStateReturn gst_rtpdec_change_state (GstElement * element); -static gboolean rtpdec_init(GstPlugin* plugin); +static gboolean rtpdec_init (GstPlugin * plugin); -static GObjectClass* parent_class = NULL; +static GObjectClass *parent_class = NULL; @@ -86,10 +87,8 @@ static GType rtpdec_type = 0; - if (!rtpdec_type) - { - static const GTypeInfo rtpdec_info = - { + if (!rtpdec_type) { + static const GTypeInfo rtpdec_info = { sizeof (GstRtpdecClass), NULL, @@ -101,8 +100,7 @@ (GInstanceInitFunc) gst_rtpdec_init, }; rtpdec_type = g_type_register_static (GST_TYPE_ELEMENT, - "GstRtpdec", - &rtpdec_info, 0); + "GstRtpdec", &rtpdec_info, 0); return rtpdec_type; @@ -110,15 +108,15 @@ /* initialize the rtpdec's class */ -gst_rtpdec_class_init (GstRtpdecClass *klass) +gst_rtpdec_class_init (GstRtpdecClass * klass) GObjectClass *gobject_class; GstElementClass *gstelement_class; GstRtpdecClass *gst_rtpdec_class; - gobject_class = (GObjectClass*) klass; - gstelement_class = (GstElementClass*) klass; - gst_rtpdec_class = (GstRtpdecClass*) klass; + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + gst_rtpdec_class = (GstRtpdecClass *) klass; gobject_class->set_property = gst_rtpdec_set_property; @@ -127,36 +125,37 @@ gstelement_class->set_clock = gst_rtpdec_set_clock; gstelement_class->release_locks = gst_rtpdec_release_locks; gstelement_class->change_state = gst_rtpdec_change_state; - gst_rtpdec_class->default_mapping = gst_rtpdec_create_av_mapping(); + gst_rtpdec_class->default_mapping = gst_rtpdec_create_av_mapping (); - parent_class = g_type_class_ref(GST_TYPE_ELEMENT); + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); -gst_rtpdec_init (GstRtpdec *rtpdec) +gst_rtpdec_init (GstRtpdec * rtpdec) - GError* error; + GError *error; GstElement *element; - element = GST_ELEMENT(rtpdec); + element = GST_ELEMENT (rtpdec); rtpdec->clock = NULL; - gst_element_set_loop_function(element, gst_rtpdec_main_loop); - rtpdec->myid = create_id(); + gst_element_set_loop_function (element, gst_rtpdec_main_loop); + rtpdec->myid = create_id (); rtpdec->mapping = NULL; - rtpdec->sender_list = g_hash_table_new(g_int_hash, g_int_equal); - rtpdec->recv_list = g_hash_table_new(g_int_hash, g_int_equal); - rtpdec->cname = make_cname(); + rtpdec->sender_list = g_hash_table_new (g_int_hash, g_int_equal); + rtpdec->recv_list = g_hash_table_new (g_int_hash, g_int_equal); + rtpdec->cname = make_cname (); rtpdec->email = NULL; - rtpdec->bandwith = 8000; rtpdec->members = 0; rtpdec->senders = 0; - rtpdec->rtcp_bw = rtpdec->bandwith/20; + rtpdec->rtcp_bw = rtpdec->bandwith / 20; rtpdec->avg_rtcp_size = 0; rtpdec->initial = 0; @@ -164,7 +163,7 @@ rtpdec->control_socket = -1; rtpdec->data_socket = -1; - rtpdec->local_address = gst_addr_any(); + rtpdec->local_address = gst_addr_any (); rtpdec->data_port = -1; rtpdec->control_port = -1; rtpdec->remote_address.alternatives = NULL; @@ -179,115 +178,115 @@ rtpdec->mtu = G_MAXINT; - pipe(rtpdec->pipe); - pipe(rtpdec->report_thread_pipe); + pipe (rtpdec->pipe); + pipe (rtpdec->report_thread_pipe); -gst_rtpdec_finalize(GstRtpdec* element) +gst_rtpdec_finalize (GstRtpdec * element) if (element->mapping) { - gst_rtpdec_delete_mapping(element->mapping); + gst_rtpdec_delete_mapping (element->mapping); if (element->sender_list) { - gst_rtpdec_delete_sender_list(element->sender_list); + gst_rtpdec_delete_sender_list (element->sender_list); if (element->recv_list) { - gst_rtpdec_delete_recv_list(element->recv_list); + gst_rtpdec_delete_recv_list (element->recv_list); - gst_addr_delete_num_address(&element->remote_address); - gst_addr_delete_num_address(&element->multicast_addr); - gst_addr_delete_authorized_addrs(&element->authorized_senders); - parent_class->finalize(G_OBJECT(element)); + gst_addr_delete_num_address (&element->remote_address); + gst_addr_delete_num_address (&element->multicast_addr); + gst_addr_delete_authorized_addrs (&element->authorized_senders); + parent_class->finalize (G_OBJECT (element)); -gst_rtpdec_main_loop(GstElement* element) +gst_rtpdec_main_loop (GstElement * element) guint data_size; - gchar* data; + gchar *data; packet_type type; - GstRtpdec* rtpdec; - rtpdec = GST_RTPDEC(element); - g_assert(rtpdec != NULL); - while (wait_for_data(rtpdec, &data_size, &data, &peer, &type)) { - if (authorized_packet(rtpdec, &peer, &type)) { - gst_rtpdec_dispatch_packet(rtpdec, data_size, data, &peer, type); + GstRtpdec *rtpdec; + rtpdec = GST_RTPDEC (element); + g_assert (rtpdec != NULL); + while (wait_for_data (rtpdec, &data_size, &data, &peer, &type)) { + if (authorized_packet (rtpdec, &peer, &type)) { + gst_rtpdec_dispatch_packet (rtpdec, data_size, data, &peer, type); -gst_rtpdec_set_clock(GstElement* element, GstClock* clock) +gst_rtpdec_set_clock (GstElement * element, GstClock * clock) - GST_RTPDEC(element)->clock = clock; + GST_RTPDEC (element)->clock = clock; -gst_rtpdec_set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) +gst_rtpdec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) int port_val; - GstAddress* addr; - GHashTable* mapping; + GstAddress *addr; + GHashTable *mapping; int bandwidth; g_return_if_fail (GST_IS_RTPDEC (object)); rtpdec = GST_RTPDEC (object); - switch (prop_id) - case ARG_LOCAL_DATA_PORT: - port_val = g_value_get_int(value); - gst_rtpdec_set_data_port(rtpdec, port_val); - case ARG_LOCAL_CONTROL_PORT: - gst_rtpdec_set_ctl_port(rtpdec, port_val); - case ARG_LOCAL_ADDR: - addr = (GstAddress*) g_value_get_boxed(value); - gst_rtpdec_set_local_addr(rtpdec, addr); - gst_address_free(addr); - case ARG_REMOTE_HOST: - gst_rtpdec_set_remote_addr(rtpdec, addr); - case ARG_REMOTE_DATA_PORT: - gst_rtpdec_set_remote_data_port(rtpdec, port_val); - case ARG_REMOTE_CONTROL_PORT: - gst_rtpdec_set_remote_ctl_port(rtpdec, port_val); - case ARG_MULTICAST_ADDR: - gst_rtpdec_set_multicast_addr(rtpdec, addr); - case ARG_MEDIA_MIME_MAPPING: - mapping = (GHashTable*) g_value_get_boxed(value); - gst_rtpdec_set_mapping(rtpdec, mapping); - case ARG_BANDWIDTH: - bandwidth = g_value_get_int(value); - gst_rtpdec_set_bandwith(rtpdec, value); - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + switch (prop_id) { + case ARG_LOCAL_DATA_PORT: + port_val = g_value_get_int (value); + gst_rtpdec_set_data_port (rtpdec, port_val); + case ARG_LOCAL_CONTROL_PORT: + gst_rtpdec_set_ctl_port (rtpdec, port_val); + case ARG_LOCAL_ADDR: + addr = (GstAddress *) g_value_get_boxed (value); + gst_rtpdec_set_local_addr (rtpdec, addr); + gst_address_free (addr); + case ARG_REMOTE_HOST: + gst_rtpdec_set_remote_addr (rtpdec, addr); + case ARG_REMOTE_DATA_PORT: + gst_rtpdec_set_remote_data_port (rtpdec, port_val); + case ARG_REMOTE_CONTROL_PORT: + gst_rtpdec_set_remote_ctl_port (rtpdec, port_val); + case ARG_MULTICAST_ADDR: + gst_rtpdec_set_multicast_addr (rtpdec, addr); + case ARG_MEDIA_MIME_MAPPING: + mapping = (GHashTable *) g_value_get_boxed (value); + gst_rtpdec_set_mapping (rtpdec, mapping); + case ARG_BANDWIDTH: + bandwidth = g_value_get_int (value); + gst_rtpdec_set_bandwith (rtpdec, value); + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -gst_rtpdec_get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) +gst_rtpdec_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) GstRtpdec *filter; @@ -295,71 +294,72 @@ filter = GST_RTPDEC (object); switch (prop_id) { -static gboolean -gst_rtpdec_release_locks(GstElement* element) +static gboolean +gst_rtpdec_release_locks (GstElement * element) - GstRtpdec* rtpdec = GST_RTPDEC(element); + GstRtpdec *rtpdec = GST_RTPDEC (element); char ctl[1]; - g_assert(element != NULL); + g_assert (element != NULL); ctl[0] = 0; write (rtpdec->pipe[0], ctl, 1); return TRUE; static GstElementStateReturn -gst_rtpdec_change_state(GstElement* element) +gst_rtpdec_change_state (GstElement * element) guint8 current_state, next_state; - current_state = GST_STATE(element); - next_state = GST_STATE_PENDING(element); + current_state = GST_STATE (element); + next_state = GST_STATE_PENDING (element); if (current_state == GST_STATE_NULL && next_state == GST_STATE_READY) { - sucess = gst_rtpdec_open_conn(rtpdec); + sucess = gst_rtpdec_open_conn (rtpdec); return sucess ? GST_STATE_SUCCESS : GST_STATE_FAILURE; } else if (current_state == GST_STATE_READY && next_state == GST_STATE_PAUSED) { - gst_rtpdec_connect(rtpdec); - } else if (current_state == GST_STATE_PAUSED && next_state == GST_STATE_PLAYING) { + gst_rtpdec_connect (rtpdec); + } else if (current_state == GST_STATE_PAUSED + && next_state == GST_STATE_PLAYING) { return GST_STATE_SUCCESS; - } else if (current_state == GST_STATE_PLAYING && next_state == GST_STATE_PAUSED) { + } else if (current_state == GST_STATE_PLAYING + && next_state == GST_STATE_PAUSED) { } else if (current_state == GST_STATE_PAUSED && next_state == GST_STATE_READY) { - gst_rtpdec_disconnect(rtpdec); + gst_rtpdec_disconnect (rtpdec); } else if (current_state == GST_STATE_READY && next_state == GST_STATE_NULL) { - gst_rtpdec_close_conn(rtpdec); + gst_rtpdec_close_conn (rtpdec); } else { - g_warning("gstrtpdec: Invalid state change"); + g_warning ("gstrtpdec: Invalid state change"); return GST_STATE_FAILURE; static gboolean -rtpdec_init (GstPlugin *plugin) +rtpdec_init (GstPlugin * plugin) - sucess = gst_element_register(plugin, "rtpdec", GST_RANK_PRIMARY, GST_RTPDEC_TYPE); + sucess = + gst_element_register (plugin, "rtpdec", GST_RANK_PRIMARY, + GST_RTPDEC_TYPE); return sucess; -GST_PLUGIN_DEFINE ( - GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "rtpdec", - "RTP decoding", - rtpdec_init, - VERSION, - "LGPL", - GST_PACKAGE, - GST_ORIGIN -) +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "rtpdec", + "RTP decoding", rtpdec_init, VERSION, "LGPL", GST_PACKAGE, GST_ORIGIN) Index: gstrtpdec.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h,v retrieving revision 1.8 diff -u -d -r1.8 -r1.9 --- a/gstrtpdec.h 5 Mar 2004 01:08:00 -0000 1.8 +++ b/gstrtpdec.h 20 Mar 2004 23:33:28 -0000 1.9 @@ -9,12 +9,12 @@ #include "rtp_packet.h" -#include "rtp_ctl_event.h" #include "gstrtphandler.h" #ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ +extern "C" +#endif /* __cplusplus */ /* #define's don't like whitespacey bits */ #define GST_RTPDEC_TYPE \ @@ -29,123 +29,127 @@ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_RTPDEC_TYPE)) #define GST_RTPDEC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_RTPDEC_TYPE, GstRtpdecClass)) -typedef struct _GstRtpdec GstRtpdec; -typedef struct _GstRtpdecClass GstRtpdecClass; + typedef struct _GstRtpdec GstRtpdec; + typedef struct _GstRtpdecClass GstRtpdecClass; -const guint32 sender_magic = 0x0c0deb12; -const guint32 recv_magic = 0x0badbeef; + const guint32 sender_magic = 0x0c0deb12; + const guint32 recv_magic = 0x0badbeef; -struct _GstRtpdecHandler; + struct _GstRtpdecHandler; -typedef struct _GstRtpdecHandler GstRtpdecHandler; + typedef struct _GstRtpdecHandler GstRtpdecHandler; -struct sender_info { - guint32 magic; - struct sockaddr_in6 socket; - gboolean received_data; - gboolean received_srvctl; - unsigned int total_packets_received; /* According to us */ - unsigned int total_packets_sent; /* According to the server, in last sender report */ - unsigned int total_packets_lost; - guint16 last_sequence_number; - unsigned int total_bytes_received; - guint32 jitter; - /* Bellow are numbers since last control packet sent */ - unsigned int packets_received; - unsigned int packets_lost; - unsigned int bytes_received; - /* From the latest control packet. Used for setting the time of the buffer */ - struct ntptime last_ctl_ntptime; - guint32 last_ctl_rtptimestamp; - /* For jitter calculation */ - guint32 last_data_timestamp; - GstClockTime time_last_data_packet_received; - GstPad* output; - unsigned int sample_rate; /* 0 means undefined, should take from the stream */ - unsigned int payload_type; - GstElement* handler_element; - GstIRtpdecHandler* handler; - gboolean removed; /* a BYE packet was received */ -}; + struct sender_info + guint32 magic; + struct sockaddr_in6 socket; + gboolean received_data; + gboolean received_srvctl; + unsigned int total_packets_received; /* According to us */ + unsigned int total_packets_sent; /* According to the server, in last sender report */ + unsigned int total_packets_lost; + guint16 last_sequence_number; + unsigned int total_bytes_received; + guint32 jitter; + /* Bellow are numbers since last control packet sent */ + unsigned int packets_received; + unsigned int packets_lost; + unsigned int bytes_received; + /* From the latest control packet. Used for setting the time of the buffer */ + struct ntptime last_ctl_ntptime; + guint32 last_ctl_rtptimestamp; + /* For jitter calculation */ + guint32 last_data_timestamp; + GstClockTime time_last_data_packet_received; + GstPad *output; + unsigned int sample_rate; /* 0 means undefined, should take from the stream */ + unsigned int payload_type; + GstElement *handler_element; + GstIRtpdecHandler *handler; + gboolean removed; /* a BYE packet was received */ + }; -struct recv_info { - GString* name; - GString* cname; - GString* email; + struct recv_info + GString *name; + GString *cname; + GString *email; -struct _GstRtpdec -{ - GstElement element; - /* mapping of payload byte => GstStructure */ - guint32 myid; - /* Mapping of identifier -> sender_info */ - GHashTable* sender_list; + struct _GstRtpdec + GstElement element; + /* mapping of payload byte => GstStructure */ + GHashTable *mapping; + guint32 myid; + /* Mapping of identifier -> sender_info */ + GHashTable *sender_list; - /* Mapping of identifier -> recv_info */ - GHashTable* recv_list; + /* Mapping of identifier -> recv_info */ + GHashTable *recv_list; - GstClock* clock; + GstClock *clock; - /* Information for scheduling the sending of control info */ - guint bandwith; /* in bytes/second */ + /* Information for scheduling the sending of control info */ + guint bandwith; /* in bytes/second */ - GTime tp; /* last time when an RTCP packet was transmitted */ - GTime tn; /* next scheduled transmission of RTCP */ - guint members; - guint senders; - guint rtcp_bw; /* bandwidth for RTCP */ - /* we_sent is false */ - guint avg_rtcp_size; - gboolean initial; /* True if no RTCP packet yet sent */ + GTime tp; /* last time when an RTCP packet was transmitted */ + GTime tn; /* next scheduled transmission of RTCP */ + guint members; + guint senders; + guint rtcp_bw; /* bandwidth for RTCP */ + /* we_sent is false */ + guint avg_rtcp_size; + gboolean initial; /* True if no RTCP packet yet sent */ - /* Network stuff */ + /* Network stuff */ - int control_socket, data_socket; + int control_socket, data_socket; - GstNumAddress local_address; - int data_port, control_port; + GstNumAddress local_address; + int data_port, control_port; - GstNumAddress remote_address; - GstNumAddress multicast_addr; + GstNumAddress remote_address; + GstNumAddress multicast_addr; - in_port_t remote_data_port, remote_control_port; - gboolean multicast_mode; - gboolean default_authorized; - GstAuthorizedAddrs authorized_senders; + in_port_t remote_data_port, remote_control_port; + gboolean multicast_mode; - guint mtu; + gboolean default_authorized; + GstAuthorizedAddrs authorized_senders; - /* Write to pipe[1] for interrupting any blocking operation */ - int pipe[2]; + guint mtu; - /* Pipe for communicating with the thread that sends reports */ - int report_thread_pipe[2]; + /* Write to pipe[1] for interrupting any blocking operation */ + int pipe[2]; - /* Possible messages sent to that thread */ - /* The expected schedule for sending the next packet changed */ + /* Pipe for communicating with the thread that sends reports */ + int report_thread_pipe[2]; + /* Possible messages sent to that thread */ + /* The expected schedule for sending the next packet changed */ #define SCHED_NEXT_PACKET_CHANGED 'S' - /* The network has told us that our packets are too large */ + /* The network has told us that our packets are too large */ #define PATH_MTU_CHANGED 'P' -struct _GstRtpdecClass - GstElementClass parent_class; - GHashTable* default_mapping; + struct _GstRtpdecClass + GstElementClass parent_class; + GHashTable *default_mapping; -GType gst_rtpdec_get_type (void); + GType gst_rtpdec_get_type (void); + GstStaticPadTemplate gst_rtpdec_src_template; -#endif /* __GST_RTPDEC_H__ */ +#endif /* __GST_RTPDEC_H__ */ Index: gstrtphandler.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtphandler.h,v --- a/gstrtphandler.h 27 Feb 2004 04:19:26 -0000 1.1 +++ b/gstrtphandler.h 20 Mar 2004 23:33:28 -0000 1.2 @@ -18,20 +18,27 @@ #define GST_IRTPDEC_HANDLER_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_IRTPDEC_HANDLER_TYPE, GstIRtpdecHandlerClass)) -typedef struct _GstIRtpdecHandlerClass { +typedef struct _GstIRtpdecHandlerClass GTypeInterface parent; - void (*init)(GstPad* output, GHashTable* metadata); - void (*get_data_packet)(GstBuffer* buffer, unsigned int data_offset, GstClockTime timestamp); - unsigned int (*get_sample_rate)(GstBuffer* buffer, unsigned int data_offset); - void (*get_app_packet)(guint32 tag, gconstpointer data, unsigned int data_size); - void (*set_caps_properties)(GstCaps* caps, GHashTable* properties); + void (*init) (GstPad * output, GHashTable * metadata); + void (*get_data_packet) (char *buffer, guint size, guint data_offset, + GstClockTime timestamp); + unsigned int (*get_sample_rate) (char *buffer, guint size, guint data_offset); + void (*get_app_packet) (guint32 tag, gconstpointer data, guint data_size); + void (*set_caps_properties) (GstCaps * caps, GHashTable * properties); } GstIRtpdecHandlerClass; -GType gst_irtpdec_handler_get_type(void); -void gst_irtpdec_handler_init(GstIRtpdecHandler* this, GstPad* output, GHashTable* metadata); -void gst_irtpdec_handler_get_data_packet(GstIRtpdecHandler* this, GstBuffer* buffer, unsigned int data_offset, GstClockTime timestamp); -void gst_irtpdec_handler_get_app_packet(GstIRtpdecHandler* this, guint32 tag, gconstpointer data, unsigned int data_size); -unsigned int gst_irtpdec_handler_get_sample_rate(GstIRtpdecHandler* this, GstBuffer* buffer, unsigned int data_offset); -void gst_irtpdec_set_caps_properties(GstCaps* caps, GHashTable* properties); +GType gst_irtpdec_handler_get_type (void); +void gst_irtpdec_handler_init (GstIRtpdecHandler * this, GstPad * output, + GHashTable * metadata); +void gst_irtpdec_handler_get_data_packet (GstIRtpdecHandler * this, + char *buffer, guint size, guint data_offset, GstClockTime timestamp); +void gst_irtpdec_handler_get_app_packet (GstIRtpdecHandler * this, guint32 tag, + gconstpointer data, guint data_size); +/* This is used for Vorbis codec, that sends the sample rate in out of band data, and so it can change on the fly */ +unsigned int gst_irtpdec_handler_get_sample_rate (GstIRtpdecHandler * this, + char *buffer, guint size, guint data_offset); +void gst_irtpdec_set_caps_properties (GstCaps * caps, GHashTable * properties); Index: ntohll.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/ntohll.h,v --- a/ntohll.h 27 Feb 2004 04:47:28 -0000 1.1 +++ b/ntohll.h 20 Mar 2004 23:33:28 -0000 1.2 -extern long long ntohll(long long n); +extern long long ntohll (long long n); Index: packet_type.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/packet_type.h,v diff -u -d -r1.2 -r1.3 --- a/packet_type.h 2 Mar 2004 06:31:12 -0000 1.2 +++ b/packet_type.h 20 Mar 2004 23:33:28 -0000 1.3 @@ -1,6 +1,7 @@ #ifndef __PACKET_TYPE_H__ #define __PACKET_TYPE_H__ -typedef enum {data_packet, control_packet} packet_type; +typedef enum +{ data_packet, control_packet } packet_type; --- rtp_ctl_event.h DELETED --- Index: rtp_packet.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_packet.h,v --- a/rtp_packet.h 27 Feb 2004 04:19:26 -0000 1.1 +++ b/rtp_packet.h 20 Mar 2004 23:33:28 -0000 1.2 @@ -1,8 +1,8 @@ -struct __attribute__((packed)) rtp_packet { +struct __attribute__ ((packed)) rtp_packet { unsigned int version:2; unsigned int padding:1; unsigned int extension:1; - unsigned int num_contrib_sources: 4; + unsigned int num_contrib_sources:4; unsigned int mark:1; unsigned int payload_type:7; unsigned int sequence_number:16; @@ -11,37 +11,39 @@ unsigned int contrib_sources[1]; -struct __attribute__((packed)) rtp_packet_extension { +struct __attribute__ ((packed)) rtp_packet_extension { guint16 tag; guint16 length; -struct __attribute__((packed)) rtcp_common_header { +struct __attribute__ ((packed)) rtcp_common_header { unsigned int num_sources:5; - enum {SENDER_REPORT = 200, RECEIVER_REPORT = 201, SOURCE_DESCRIPTION = 202, - BYE = 203, APP = 204} packet_type:8; - unsigned int length: 16; + { SENDER_REPORT = 200, RECEIVER_REPORT = 201, SOURCE_DESCRIPTION = 202, + BYE = 203, APP = 204 + } packet_type:8; + unsigned int length:16; -struct __attribute__((packed)) reception_block { +struct __attribute__ ((packed)) reception_block { guint32 identifier; guint8 fraction_lost_last; - unsigned int cumul_packets_lost: 24; + unsigned int cumul_packets_lost:24; guint32 highest_sequence_number; guint32 jitter; guint32 last_timestamp_seen; guint32 time_since_last_packet; -struct __attribute__((packed)) ntptime { +struct __attribute__ ((packed)) ntptime { guint32 integer; guint32 frac; -struct __attribute__((packed)) rtcp_sender_report { +struct __attribute__ ((packed)) rtcp_sender_report { struct rtcp_common_header common; guint32 sync_src_rtcp_sender; struct ntptime ntp_timestamp; @@ -51,7 +53,7 @@ struct reception_block reception_blocks[1]; -struct __attribute__((packed)) rtcp_recv_report { +struct __attribute__ ((packed)) rtcp_recv_report { @@ -59,24 +61,26 @@ -struct __attribute__((packed)) rtcp_sdes { +struct __attribute__ ((packed)) rtcp_sdes { - struct __attribute__((packed)) sdes_chunk { - guint32 identifier; /* sync source or contrib source */ - struct __attribute__((packed)) sdes_item { - enum {END = 0, CNAME=1, NAME=2, EMAIL=3, PHONE=4, STREET_ADDRESS=5, TOOL=6, NOTE=7, PRIV=8} type: 8; + struct __attribute__ ((packed)) sdes_chunk { + guint32 identifier; /* sync source or contrib source */ + struct __attribute__ ((packed)) sdes_item { + enum + { END = 0, CNAME = 1, NAME = 2, EMAIL = 3, PHONE = 4, STREET_ADDRESS = + 5, TOOL = 6, NOTE = 7, PRIV = 8 } type:8; guint8 length; gchar text[1]; - } items[1]; /* WARNING: Variable length struct. Do not use the array index for values other than 0*/ - } chunks[1]; /* Idem here */ + } items[1]; /* WARNING: Variable length struct. Do not use the array index for values other than 0 */ + } chunks[1]; /* Idem here */ -struct __attribute__((packed)) rtcp_bye { +struct __attribute__ ((packed)) rtcp_bye { guint32 identifier[1]; -struct __attribute__((packed)) rtcp_app { +struct __attribute__ ((packed)) rtcp_app { guint32 name; Index: rtp_report.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_report.c,v retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- a/rtp_report.c 2 Mar 2004 22:53:06 -0000 1.4 +++ b/rtp_report.c 20 Mar 2004 23:33:28 -0000 1.5 @@ -1,20 +1,21 @@ -#include "rtp-report.h" +#include "rtp_report.h" #include "gstrtpdec.h" gpointer -gst_rtpdec_send_report_thread(gpointer ptr) +gst_rtpdec_send_report_thread (gpointer ptr) - GstRtpdec* rtpdec = (GstRtpdec*) ptr; + GstRtpdec *rtpdec = (GstRtpdec *) ptr; gboolean do_exit; guint wait_time; - while(1) { - wait_time = gst_rtpdec_get_interval_for_report(rtpdec); - do_exit = gst_rtpdec_wait(rtpdec, wait_time); - if (do_exit){ + while (1) { + wait_time = gst_rtpdec_get_interval_for_report (rtpdec); + do_exit = gst_rtpdec_wait (rtpdec, wait_time); + if (do_exit) { - gst_rtpdec_send_report(rtpdec); + gst_rtpdec_send_report (rtpdec); return NULL; @@ -51,20 +52,19 @@ */ static guint -gst_rtpdec_get_interval_for_report(GstRtpdec* rtpdec) +gst_rtpdec_get_interval_for_report (GstRtpdec * rtpdec) -gst_rtpdec_wait(GstRtpdec* rtpdec, guint wait_time) +gst_rtpdec_wait (GstRtpdec * rtpdec, guint wait_time) -gst_rtpdec_send_report(GstRtpdec* rtpdec) +gst_rtpdec_send_report (GstRtpdec * rtpdec) -} +} Index: rtp_report.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_report.h,v --- a/rtp_report.h 2 Mar 2004 06:31:12 -0000 1.2 +++ b/rtp_report.h 20 Mar 2004 23:33:28 -0000 1.3 @@ -2,5 +2,5 @@ #define __RTP_REPORT_H__ 1 #include <glib/gtypes.h> -gpointer gst_rtpdec_send_report_thread(gpointer ptr); +gpointer gst_rtpdec_send_report_thread (gpointer ptr); Index: rtpdec.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtpdec.c,v --- a/rtpdec.c 17 Mar 2004 23:54:07 -0000 1.4 +++ b/rtpdec.c 20 Mar 2004 23:33:28 -0000 1.5 @@ -1,382 +1,439 @@ -#include "gstrtpdec.h" +#include "rtpdec.h" +#include <pwd.h> -static void gst_rtpdec_handle_control_packet(GstRtpdec* element, char* data, int data_size); +static void gst_rtpdec_handle_control_packet (GstRtpdec * element, char *data, + guint data_size); -static void gst_rtpdec_handle_rtcp_sender_report(GstRtpdec* element, struct rtcp_sender_report* packet); +static void gst_rtpdec_handle_rtcp_sender_report (GstRtpdec * element, [...1031 lines suppressed...] + pass = getpwuid (getuid ()); + strncpy (buffer, pass->pw_name, buf_size); -gst_rtpdec_connect(GstRtpdec* element) +gst_rtpdec_connect (GstRtpdec * element) -gst_rtpdec_disconnect(GstRtpdec* element) +gst_rtpdec_disconnect (GstRtpdec * element) Index: rtpdec.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtpdec.h,v --- a/rtpdec.h 8 Mar 2004 23:35:52 -0000 1.6 +++ b/rtpdec.h 20 Mar 2004 23:33:28 -0000 1.7 @@ -6,24 +6,25 @@ #include "packet_type.h" -GHashTable* gst_rtpdec_create_av_mapping(); +GHashTable *gst_rtpdec_create_av_mapping (); -void gst_rtpdec_dispatch_packet(GstRtpdec* rtpdec, guint size, gchar* data, struct sockaddr_in6* source, packet_type type); +void gst_rtpdec_dispatch_packet (GstRtpdec * rtpdec, guint size, gchar * data, + struct sockaddr_in6 *source, packet_type type); -void gst_rtpdec_set_mapping(GstRtpdec* rtpdec, GHashTable* mapping); +void gst_rtpdec_set_mapping (GstRtpdec * rtpdec, GHashTable * mapping); -void gst_rtpdec_disconnect(GstRtpdec* rtpdec); +void gst_rtpdec_disconnect (GstRtpdec * rtpdec); -void gst_rtpdec_connect(GstRtpdec* rtpdec); +void gst_rtpdec_connect (GstRtpdec * rtpdec); -guint32 createid(void); +guint32 createid (void); -GString* make_cname(void); +GString *make_cname (void); -void gst_rtpdec_delete_mapping(GHashTable* mapping); +void gst_rtpdec_delete_mapping (GHashTable * mapping); -void gst_rtpdec_delete_sender_list(GHashTable* sender_list); +void gst_rtpdec_delete_sender_list (GHashTable * sender_list); -void gst_rtpdec_delete_recv_list(GHashTable* recv_list); +void gst_rtpdec_delete_recv_list (GHashTable * recv_list); Index: socket_fns.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/socket_fns.c,v diff -u -d -r1.5 -r1.6 --- a/socket_fns.c 9 Mar 2004 17:28:48 -0000 1.5 +++ b/socket_fns.c 20 Mar 2004 23:33:28 -0000 1.6 @@ -1,176 +1,241 @@ -#include <sys/poll.h> #include "socket_fns.h" +#include <sys/poll.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <netinet/in.h> -static void handle_error_message(GstRtpdec* dec, int fd); +#define HAVE_USER_PMTU -gboolean wait_for_data(GstRtpdec* element, - gunit* data_size, gchar** data, struct sockaddr_in6 *peer, packet_type* type) +#ifdef HAVE_USER_PMTU +#include <errno.h> +struct sock_extended_err + guint32 ee_errno; + guint8 ee_origin; + guint8 ee_type; + guint8 ee_code; + guint8 ee_pad; + guint32 ee_info; + guint32 ee_data; +}; +#endif +static void handle_error_message (const GstRtpdec * dec, int fd); +static gboolean try_bind (GstRtpdec * element, in_port_t port, int *socket); +static gboolean try_bind_random (GstRtpdec * element, int *socket); +static gboolean try_bind_both_random (GstRtpdec * element); +static gboolean subscribe_multicast (GstRtpdec * element, int fd, + GstNumAddress multicast_addr); +static void handle_error_message (const GstRtpdec * element, int fd); +static void user_path_mtu (int fd); +static void set_mtu (GstRtpdec * element, guint mtu); +wait_for_data (const GstRtpdec * element, + guint * data_size, gchar ** data, struct sockaddr_in6 *peer, + packet_type * type) struct pollfd fds[3] = { {.fd = element->control_socket, - .events = POLLIN | POLLERR, - .revents = 0}, + .events = POLLIN | POLLERR, +#else + .events = POLLERR + .revents = 0}, {.fd = element->data_socket, - {.fd = element->pipe, - .events = POLLIN, - .revents = 0}}; + .events = POLLIN, + {.fd = element->pipe[0], + .revents = 0} gboolean try_again; do { - poll(&fds, 3, -1); - if (fd[2].revents & POLLIN) { + poll (fds, 3, -1); + if (fds[2].revents & POLLIN) { *data_size = 0; *data = NULL; return FALSE; - } else if ((fd[0].revents & POLLIN) || (fd[1].revents & POLLIN)) { + } else if ((fds[0].revents & POLLIN) || (fds[1].revents & POLLIN)) { int active_fd; - if (fd[0].revents & POLLIN) { + guint foo; + if (fds[0].revents & POLLIN) { active_fd = element->control_socket; *type = control_packet; } else { active_fd = element->data_socket; *type = data_packet; } - ioctl(active_fd, FIONREAD, data_size); - *data = g_malloc(*data_size); - recvfrom(active_fd, data, *data_size, 0, - peer, sizeof(struct sockaddr_in6)); + ioctl (active_fd, FIONREAD, data_size); + *data = g_malloc (*data_size); + foo = sizeof (struct sockaddr_in6); + recvfrom (active_fd, data, *data_size, 0, (struct sockaddr *) peer, &foo); try_again = FALSE; - } else if ((fd[0].revents & POLLERR) || (fd[1].revents & POLLERR)) { + } else if (fds[0].revents & POLLERR) { - if (fd[0].revents & POLLERR) { - active_fd = element->control_socket; - } else { - active_fd = element->data_socket; - } - handle_error_message(element, active_fd); + active_fd = element->control_socket; + handle_error_message (element, active_fd); try_again = TRUE; - } while(try_again); + } while (try_again); - -static void handle_error_message(GstRtpdec* element, int fd) +/* The code bellow is Linux specific. No standard way of doing + PATH MTU by hand is known */ +handle_error_message (const GstRtpdec * element, int fd) - struct sock_extended_err* sock_error; + struct sock_extended_err *sock_error; /* FIXME: reliable way of knowning size of the buffer bellow?? */ - char buf[CMSG_SPACE(sizeof sock_extended_err) + sizeof(struct sockaddr_in6) + 256]; + char buf[CMSG_SPACE (sizeof (struct sock_extended_err)) + + sizeof (struct sockaddr_in6) + 256]; struct msghdr msg = { .msg_name = &peer, - .msg_name_len = sizeof(struct sockaddr_in6), + .msg_namelen = sizeof (struct sockaddr_in6), .msg_iov = NULL, .msg_iovlen = 0, .msg_control = buf, - .msg_control_len = sizeof(buf), - .msg_flags = MSG_ERRQUEUE}; - struct cmsghdr* cmsg; - recvmsg(fd, &msg, MSG_ERRQUEUE); - for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; - cmsg = CMSG_NXTHDR(&msg, cmsg)) { + .msg_controllen = sizeof (buf), + .msg_flags = MSG_ERRQUEUE + struct cmsghdr *cmsg; + recvmsg (fd, &msg, MSG_ERRQUEUE); + for (cmsg = CMSG_FIRSTHDR (&msg); cmsg != NULL; + cmsg = CMSG_NXTHDR (&msg, cmsg)) { if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR) { - sock_error = (struct sock_extended_err*) CMSG_DATA(cmsg); + sock_error = (struct sock_extended_err *) CMSG_DATA (cmsg); if (sock_error->ee_errno == EMSGSIZE) { - set_mtu(element, sock_error->ee_info); + set_mtu ((GstRtpdec *) element, sock_error->ee_info); -static void set_mtu(GstRtpdec* element, unsigned int mtu) +set_mtu (GstRtpdec * element, guint mtu) char m = PATH_MTU_CHANGED; element->mtu = mtu; - write(element->report_thread_pipe[1], &m, 1); + write (element->report_thread_pipe[1], &m, 1); -void -authorized_packet(GstRtpdec* element, struct sockaddr_in6* addr, packet_type* type) +authorized_packet (GstRtpdec * element, struct sockaddr_in6 *addr, - if (element->default_authorized) { - if (element->multicast_mode) { - return TRUE; - } else { - return gst_addr_in_list(element->remote_address); + if (element->default_authorized) { + if (element->multicast_mode) { + return TRUE; } else { - return gst_addr_allowed(element->authorized_senders, addr); + return gst_addr_in_list (element->remote_address, &addr->sin6_addr); + } else { + return gst_addr_allowed (element->authorized_senders, addr); -gst_rtpdec_open_conn(GstElement* element) +gst_rtpdec_open_conn (GstElement * element) gboolean bound; bound = FALSE; if (element->data_port <= 0 && element->control_port <= 0) { - bound = try_bind(element, 5004, &element->data_socket); + bound = try_bind (element, 5004, &element->data_socket); if (bound) { - bound = try_bind(element, 5005, &element->control_socket); + bound = try_bind (element, 5005, &element->control_socket); if (!bound) { - close(element->data_socket); + close (element->data_socket); if (!bound) { - bound = try_bind_both_random(element); + bound = try_bind_both_random (element); if (!bound) goto error; } else if (element->data_port > 0 && element->control_port <= 0) { - bound = try_bind(element, element->data_port, &element->data_socket); + bound = try_bind (element, element->data_port, &element->data_socket); - bound = try_bind(element, element->data_port + 1, &element->control_socket); + bound = + try_bind (element, element->data_port + 1, &element->control_socket); - bound = try_bind_random(element, &element->control_socket); + bound = try_bind_random (element, &element->control_socket); - if (!bound) + if (!bound) - bound = try_bind(element, element->control_port, &element->control_socket); + bound = try_bind (element, element->control_port, &element->control_socket); - if (element->multicas_mode) { - sucess = subscribe_multicast(element->data_socket, element->multicast_addr); + if (element->multicast_mode) { + sucess = + subscribe_multicast (element->data_socket, element->multicast_addr); if (!sucess) - sucess = subscribe_multicast(element->control_socket, element->multicast_addr); + subscribe_multicast (element->control_socket, element->multicast_addr); - sucess = gst_addr_try_connect(element->data_socket, element->remote_addr, element->remote_data_port); - if (!sucess) + gst_addr_try_connect (element->data_socket, element->remote_addr, + element->remote_data_port); + if (!sucess) - sucess = gst_addr_try_connect(element->control_socket, element->remote_addr, element->remote_control_port); + gst_addr_try_connect (element->control_socket, element->remote_addr, + element->remote_control_port); + user_path_mtu (element->control_socket); - error: +error: if (element->control_socket >= 0) { - close(element->control_socket); + close (element->control_socket); if (element->data_socket >= 0) { - close(element->data_socket); + close (element->data_socket); return FALSE; -gboolen -try_bind(GstRtpdec* element, in_port_t port, int* socket) +try_bind (GstRtpdec * element, in_port_t port, int *socket) struct sockaddr_in6 addr; gboolean result; - *socket = socket(AF_INET6, SOCK_DGRAM, 0); - result = gst_addr_try_bind(*socket, element->local_address, port); + *socket = socket (AF_INET6, SOCK_DGRAM, 0); + result = gst_addr_try_bind (*socket, element->local_address, port); if (!result) { - close(*socket); + close (*socket); *socket = -1; return result; @@ -178,38 +243,42 @@ -try_bind_random(GstRtpdec* element, int* socket) +try_bind_random (GstRtpdec * element, int *socket) - result = gst_addr_try_bind(*socket, element->local_address, 0); + result = gst_addr_try_bind (*socket, element->local_address, 0); -try_bind_both_random(element) +try_bind_both_random (GstRtpdec * element) gboolean sucess_1, sucess_2; - sucess_1 = try_bind_random(element, &element->data_socket); - if (!sucess_1) + sucess_1 = try_bind_random (element, &element->data_socket); + if (!sucess_1) return FALSE; - sucess_2 = try_bind_random(element, &element->control_socket); + sucess_2 = try_bind_random (element, &element->control_socket); return success_2; -subscribe_multicast(GstRtpdec* element, int fd, GstNumAddress multicast_addr) +subscribe_multicast (GstRtpdec * element, int fd, GstNumAddress multicast_addr) unsigned int i; - struct in6_addr* the_addr; + struct in6_addr *the_addr; struct ipv6_mreq ipv6_mreq; for (i = 0; i < multicast_addr.alternatives->len; i++) { - the_addr = g_array_index(multicast_addr.alternatives, struct in6_addr, i); + the_addr = g_array_index (multicast_addr.alternatives, struct in6_addr, i); ipv6_mreq.ipv6mr_multiaddr = *the_addr; /* FIXME: the user should be able to choose an interface */ ipv6_mreq.ipv6mr_interface = 0; - error = setsockopt(fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &ipv6_mreq); + error = setsockopt (fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &ipv6_mreq); @@ -217,9 +286,18 @@ return error == 0; -void gst_rtpdec_close_conn(GstRtpdec* element) +user_path_mtu (int fd) - close(element->data_socket); - close(element->control_socket); + guint int_true = 1; + setsockopt (fd, SOL_IP, IP_RECVERR, &int_true, sizeof (int_true)); + setsockopt (fd, SOL_IP, IP_PMTU_DISCOVER, &int_true, sizeof (int_true)); +gst_rtpdec_close_conn (GstRtpdec * element) + close (element->data_socket); + close (element->control_socket); Index: socket_fns.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/socket_fns.h,v --- a/socket_fns.h 17 Mar 2004 23:54:07 -0000 1.5 +++ b/socket_fns.h 20 Mar 2004 23:33:28 -0000 1.6 @@ -4,28 +4,30 @@ -gboolean wait_for_data(const GstRtpdec* element, - guint* data_size, gchar** data, struct sockaddr_in6 *peer, packet_type* type); +gboolean wait_for_data (const GstRtpdec * element, + packet_type * type); -gboolean authorized_packet(const GstRtpdec* element, struct sockaddr_in6* addr, packet_type* type); +gboolean authorized_packet (const GstRtpdec * element, + struct sockaddr_in6 *addr, packet_type * type); -gboolean gst_rtpdec_open_conn(GstRtpdec* element); +gboolean gst_rtpdec_open_conn (GstRtpdec * element); -void gst_rtpdec_close_conn(GstRtpdec* element); +void gst_rtpdec_close_conn (GstRtpdec * element); -void gst_rtpdec_set_data_port(GstRtpdec* rtpdec, int port); +void gst_rtpdec_set_data_port (GstRtpdec * rtpdec, int port); -void gst_rtpdec_set_ctl_port(GstRtpdec* rtpdec, int port); +void gst_rtpdec_set_ctl_port (GstRtpdec * rtpdec, int port); -void gst_rtpdec_set_local_addr(GstRtpdec* rtpdec, GstAddress* addr); +void gst_rtpdec_set_local_addr (GstRtpdec * rtpdec, GstAddress * addr); -void gst_rtpdec_set_remote_addr(GstRtpdec* rtpdec, GstAddress* addr); +void gst_rtpdec_set_remote_addr (GstRtpdec * rtpdec, GstAddress * addr); -void gst_rtpdec_set_remote_data_port(GstRtpdec* rtpdec, int port); +void gst_rtpdec_set_remote_data_port (GstRtpdec * rtpdec, int port); -void gst_rtpdec_set_remote_ctl_port(GstRtpdec* rtpdec, int port); +void gst_rtpdec_set_remote_ctl_port (GstRtpdec * rtpdec, int port); -void gst_rtpdec_set_multicast_addr(GstRtpdec* rtpdec, GstAddress* addr); +void gst_rtpdec_set_multicast_addr (GstRtpdec * rtpdec, GstAddress * addr); |
From: Ramon G. F. <ra...@pd...> - 2004-03-21 23:31:52
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Sun Mar 21 2004 15:31:45 PST Log message: It compiles Modified files: rtpdec : Makefile address.h rtp_report.c socket_fns.c Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/Makefile.diff?r1=1.2&r2=1.3 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/address.h.diff?r1=1.7&r2=1.8 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_report.c.diff?r1=1.5&r2=1.6 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/socket_fns.c.diff?r1=1.6&r2=1.7 ====Begin Diffs==== Index: Makefile =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/Makefile,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- a/Makefile 20 Mar 2004 23:33:28 -0000 1.2 +++ b/Makefile 21 Mar 2004 23:31:33 -0000 1.3 @@ -1,4 +1,4 @@ -CFLAGS=$(shell pkg-config --cflags gstreamer-0.7) -DGST_PACKAGE='"GStreamer"' -DGST_ORIGIN='"http://gstreamer.net"' -DVERSION='"0.0"' +CFLAGS=$(shell pkg-config --cflags gstreamer-0.7) -DGST_PACKAGE='"GStreamer"' -DGST_ORIGIN='"http://gstreamer.net"' -DVERSION='"0.0"' -Werror check: gstrtpdec.o rtpdec.o rtp_report.o socket_fns.o @@ -12,4 +12,4 @@ libtool --mode=compile gcc $(CFLAGS) -c rtp_report.c socket_fns.o: socket_fns.c - libtool --mode=compile gcc $(CFLAGS) -c socket_fns.c \ No newline at end of file + libtool --mode=compile gcc $(CFLAGS) -c socket_fns.c Index: address.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/address.h,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- a/address.h 20 Mar 2004 23:33:28 -0000 1.7 +++ b/address.h 21 Mar 2004 23:31:33 -0000 1.8 @@ -57,7 +57,7 @@ void gst_addr_resolve_address (const GstAddress * address, GstNumAddress * result); -gboolean gst_addr_in_list (const GstAddress * address, struct in6_addr *addr); +gboolean gst_addr_in_list (const GstNumAddress * address, struct in6_addr *addr); gboolean gst_addr_try_bind (int socket, const GstNumAddress * address, in_port_t port); Index: rtp_report.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_report.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- a/rtp_report.c 20 Mar 2004 23:33:28 -0000 1.5 +++ b/rtp_report.c 21 Mar 2004 23:31:33 -0000 1.6 @@ -2,6 +2,13 @@ #include "gstrtpdec.h" + +static guint get_interval_for_report(GstRtpdec* rtpdec); +static gboolean wait(GstRtpdec* rtpdec, guint wait_time); +static void send_report(GstRtpdec* rtpdec); gpointer gst_rtpdec_send_report_thread (gpointer ptr) { @@ -10,12 +17,12 @@ guint wait_time; while (1) { - wait_time = gst_rtpdec_get_interval_for_report (rtpdec); - do_exit = gst_rtpdec_wait (rtpdec, wait_time); + wait_time = get_interval_for_report (rtpdec); + do_exit = wait (rtpdec, wait_time); if (do_exit) { break; } - gst_rtpdec_send_report (rtpdec); + send_report (rtpdec); } return NULL; } @@ -52,19 +59,19 @@ */ static guint -gst_rtpdec_get_interval_for_report (GstRtpdec * rtpdec) +get_interval_for_report (GstRtpdec * rtpdec) static gboolean -gst_rtpdec_wait (GstRtpdec * rtpdec, guint wait_time) +wait (GstRtpdec * rtpdec, guint wait_time) static void -gst_rtpdec_send_report (GstRtpdec * rtpdec) +send_report (GstRtpdec * rtpdec) Index: socket_fns.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/socket_fns.c,v diff -u -d -r1.6 -r1.7 --- a/socket_fns.c 20 Mar 2004 23:33:28 -0000 1.6 +++ b/socket_fns.c 21 Mar 2004 23:31:33 -0000 1.7 @@ -142,14 +142,14 @@ #endif gboolean -authorized_packet (GstRtpdec * element, struct sockaddr_in6 *addr, +authorized_packet (const GstRtpdec * element, struct sockaddr_in6 *addr, packet_type * type) if (element->default_authorized) { if (element->multicast_mode) { return TRUE; } else { - return gst_addr_in_list (element->remote_address, &addr->sin6_addr); + return gst_addr_in_list (&element->remote_address, &addr->sin6_addr); } else { return gst_addr_allowed (element->authorized_senders, addr); @@ -157,7 +157,7 @@ -gst_rtpdec_open_conn (GstElement * element) +gst_rtpdec_open_conn (GstRtpdec * element) int error; gboolean bound; @@ -193,22 +193,24 @@ bound = try_bind (element, element->control_port, &element->control_socket); if (element->multicast_mode) { + gboolean sucess; sucess = - subscribe_multicast (element->data_socket, element->multicast_addr); + subscribe_multicast (element, element->data_socket, element->multicast_addr); if (!sucess) goto error; - subscribe_multicast (element->control_socket, element->multicast_addr); + subscribe_multicast (element, element->control_socket, element->multicast_addr); - gst_addr_try_connect (element->data_socket, element->remote_addr, + gst_addr_try_connect (element->data_socket, &element->remote_address, element->remote_data_port); - gst_addr_try_connect (element->control_socket, element->remote_addr, + gst_addr_try_connect (element->control_socket, &element->remote_address, element->remote_control_port); @@ -226,17 +228,17 @@ -try_bind (GstRtpdec * element, in_port_t port, int *socket) +try_bind (GstRtpdec * element, in_port_t port, int* socket_fd) struct sockaddr_in6 addr; int i; gboolean result; - *socket = socket (AF_INET6, SOCK_DGRAM, 0); - result = gst_addr_try_bind (*socket, element->local_address, port); + *socket_fd = socket (AF_INET6, SOCK_DGRAM, 0); + result = gst_addr_try_bind (*socket_fd, &element->local_address, port); if (!result) { - close (*socket); - *socket = -1; + close (*socket_fd); + *socket_fd = -1; return result; @@ -249,7 +251,7 @@ - result = gst_addr_try_bind (*socket, element->local_address, 0); + result = gst_addr_try_bind (*socket, &element->local_address, 0); @@ -261,7 +263,7 @@ if (!sucess_1) return FALSE; sucess_2 = try_bind_random (element, &element->control_socket); - return success_2; + return sucess_2; @@ -273,12 +275,13 @@ for (i = 0; i < multicast_addr.alternatives->len; i++) { - the_addr = g_array_index (multicast_addr.alternatives, struct in6_addr, i); + the_addr = &g_array_index (multicast_addr.alternatives, struct in6_addr, i); ipv6_mreq.ipv6mr_multiaddr = *the_addr; /* FIXME: the user should be able to choose an interface */ ipv6_mreq.ipv6mr_interface = 0; - error = setsockopt (fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &ipv6_mreq); + error = setsockopt (fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, + &ipv6_mreq, sizeof(ipv6_mreq) ); if (error == 0) { @@ -289,10 +292,12 @@ user_path_mtu (int fd) - guint int_true = 1; + guint int_opt; - setsockopt (fd, SOL_IP, IP_RECVERR, &int_true, sizeof (int_true)); - setsockopt (fd, SOL_IP, IP_PMTU_DISCOVER, &int_true, sizeof (int_true)); + int_opt = 1; + setsockopt (fd, IPPROTO_IPV6, IPV6_RECVERR, &int_opt, sizeof (int_opt)); + int_opt = IPV6_PMTUDISC_WANT; + setsockopt (fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &int_opt, sizeof (int_opt)); void |
From: Ramon G. F. <ra...@pd...> - 2004-04-09 00:58:03
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Thu Apr 08 2004 17:57:59 PDT Log message: Working on sending receiver reports Modified files: rtpdec : address.h gstrtpdec.h rtp_packet.h rtp_report.c socket_fns.c Added files: rtpdec : todo Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/address.h.diff?r1=1.8&r2=1.9 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h.diff?r1=1.9&r2=1.10 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_packet.h.diff?r1=1.2&r2=1.3 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_report.c.diff?r1=1.6&r2=1.7 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/socket_fns.c.diff?r1=1.7&r2=1.8 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/todo?rev=1.1&content-type=text/vnd.viewcvs-markup ====Begin Diffs==== Index: address.h =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/address.h,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- a/address.h 21 Mar 2004 23:31:33 -0000 1.8 +++ b/address.h 9 Apr 2004 00:57:47 -0000 1.9 @@ -57,7 +57,8 @@ void gst_addr_resolve_address (const GstAddress * address, GstNumAddress * result); -gboolean gst_addr_in_list (const GstNumAddress * address, struct in6_addr *addr); +gboolean gst_addr_in_list (const GstNumAddress * address, + struct in6_addr *addr); gboolean gst_addr_try_bind (int socket, const GstNumAddress * address, in_port_t port); Index: gstrtpdec.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h,v retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- a/gstrtpdec.h 20 Mar 2004 23:33:28 -0000 1.9 +++ b/gstrtpdec.h 9 Apr 2004 00:57:47 -0000 1.10 @@ -11,11 +11,7 @@ #include "rtp_packet.h" #include "gstrtphandler.h" -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - +G_BEGIN_DECLS /* #define's don't like whitespacey bits */ #define GST_RTPDEC_TYPE \ (gst_rtpdec_get_type()) @@ -28,128 +24,134 @@ #define GST_IS_RTPDEC_CLASS(obj) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_RTPDEC_TYPE)) #define GST_RTPDEC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_RTPDEC_TYPE, GstRtpdecClass)) +typedef struct _GstRtpdec GstRtpdec; +typedef struct _GstRtpdecClass GstRtpdecClass; - typedef struct _GstRtpdec GstRtpdec; - typedef struct _GstRtpdecClass GstRtpdecClass; +const guint32 sender_magic = 0x0c0deb12; +const guint32 recv_magic = 0x0badbeef; - const guint32 sender_magic = 0x0c0deb12; - const guint32 recv_magic = 0x0badbeef; +struct _GstRtpdecHandler; - struct _GstRtpdecHandler; +typedef struct _GstRtpdecHandler GstRtpdecHandler; - typedef struct _GstRtpdecHandler GstRtpdecHandler; +struct sender_info +{ + guint32 magic; + guint32 identifier; + struct sockaddr_in6 socket; + gboolean received_data; + gboolean received_srvctl; + unsigned int total_packets_received; /* According to us */ + unsigned int total_packets_sent; /* According to the server, in last sender report */ + unsigned int total_packets_lost; + guint16 last_sequence_number; + unsigned int total_bytes_received; + guint32 jitter; + /* Bellow are numbers since last control packet sent */ + unsigned int packets_received; + unsigned int packets_lost; + unsigned int bytes_received; + /* From the latest control packet. Used for setting the time of the buffer */ + struct ntptime last_ctl_ntptime; + guint32 last_ctl_rtptimestamp; + /* For jitter calculation */ + guint32 last_data_timestamp; + GstClockTime time_last_data_packet_received; + GstPad *output; + unsigned int sample_rate; /* 0 means undefined, should take from the stream */ + unsigned int payload_type; + GstElement *handler_element; + GstIRtpdecHandler *handler; + gboolean removed; /* a BYE packet was received */ + GCList *link_at_rr; +}; - struct sender_info - { - guint32 magic; - struct sockaddr_in6 socket; - gboolean received_data; - gboolean received_srvctl; - unsigned int total_packets_received; /* According to us */ - unsigned int total_packets_sent; /* According to the server, in last sender report */ - unsigned int total_packets_lost; - guint16 last_sequence_number; - unsigned int total_bytes_received; - guint32 jitter; - /* Bellow are numbers since last control packet sent */ - unsigned int packets_received; - unsigned int packets_lost; - unsigned int bytes_received; - /* From the latest control packet. Used for setting the time of the buffer */ - struct ntptime last_ctl_ntptime; - guint32 last_ctl_rtptimestamp; - /* For jitter calculation */ - guint32 last_data_timestamp; - GstClockTime time_last_data_packet_received; - GstPad *output; - unsigned int sample_rate; /* 0 means undefined, should take from the stream */ - unsigned int payload_type; - GstElement *handler_element; - GstIRtpdecHandler *handler; - gboolean removed; /* a BYE packet was received */ - }; +struct recv_info + GString *name; + GString *cname; + GString *email; - struct recv_info - GString *name; - GString *cname; - GString *email; +struct _GstRtpdec + GstElement element; + /* mapping of payload byte => GstStructure */ + GHashTable *mapping; + guint32 myid; + /* Mapping of identifier -> sender_info */ + GHashTable *sender_list; - struct _GstRtpdec - GstElement element; - /* mapping of payload byte => GstStructure */ - GHashTable *mapping; - guint32 myid; - /* Mapping of identifier -> sender_info */ - GHashTable *sender_list; + /* List of identifiers in a circular list, + so that some of them can be choosen in a round-robin + fashion, for including in the receiver reports */ + GCList *sender_list_rr; - /* Mapping of identifier -> recv_info */ - GHashTable *recv_list; + /* Mapping of identifier -> recv_info */ + GHashTable *recv_list; - GstClock *clock; + GstClock *clock; - /* Information for scheduling the sending of control info */ - guint bandwith; /* in bytes/second */ + /* Information for scheduling the sending of control info */ + guint bandwith; /* in bytes/second */ - GTime tp; /* last time when an RTCP packet was transmitted */ - GTime tn; /* next scheduled transmission of RTCP */ - guint members; - guint senders; - guint rtcp_bw; /* bandwidth for RTCP */ - /* we_sent is false */ - guint avg_rtcp_size; - gboolean initial; /* True if no RTCP packet yet sent */ + guint members; + guint senders; + guint rtcp_bw; /* bandwidth for RTCP in bytes per second */ + /* we_sent is false */ + guint avg_rtcp_size; + gboolean initial; /* True if no RTCP packet yet sent */ - /* Network stuff */ + /* Network stuff */ - int control_socket, data_socket; + int control_socket, data_socket; - GstNumAddress local_address; - int data_port, control_port; + GstNumAddress local_address; + int data_port, control_port; - GstNumAddress remote_address; - GstNumAddress multicast_addr; + GstNumAddress remote_address; + GstNumAddress multicast_addr; - in_port_t remote_data_port, remote_control_port; - gboolean multicast_mode; + in_port_t remote_data_port, remote_control_port; + gboolean multicast_mode; - gboolean default_authorized; - GstAuthorizedAddrs authorized_senders; + gboolean default_authorized; + GstAuthorizedAddrs authorized_senders; - guint mtu; + guint mtu; - /* Write to pipe[1] for interrupting any blocking operation */ - int pipe[2]; + /* Write to pipe[1] for interrupting any blocking operation */ + int pipe[2]; - /* Pipe for communicating with the thread that sends reports */ - int report_thread_pipe[2]; + /* Pipe for communicating with the thread that sends reports */ + int report_thread_pipe[2]; - /* Possible messages sent to that thread */ - /* The expected schedule for sending the next packet changed */ -#define SCHED_NEXT_PACKET_CHANGED 'S' - /* The network has told us that our packets are too large */ + /* Possible messages sent to that thread */ + /* A new member has been received. This causes the scheduling of the sending + of the next packet to change */ +#define NEW_MEMBER 'N' + /* A member has left. Like above */ +#define LEFT_MEMBER 'L' + /* The network has told us that our packets are too large */ #define PATH_MTU_CHANGED 'P' - struct _GstRtpdecClass - GstElementClass parent_class; - GHashTable *default_mapping; + /* Terminate */ +#define TERMINATE 'T' - GType gst_rtpdec_get_type (void); +struct _GstRtpdecClass + GstElementClass parent_class; + GHashTable *default_mapping; - GstStaticPadTemplate gst_rtpdec_src_template; +GType gst_rtpdec_get_type (void); -} +GstStaticPadTemplate gst_rtpdec_src_template; -#endif /* __GST_RTPDEC_H__ */ +G_END_DECLS +#endif /* __GST_RTPDEC_H__ */ Index: rtp_packet.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_packet.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- a/rtp_packet.h 20 Mar 2004 23:33:28 -0000 1.2 +++ b/rtp_packet.h 9 Apr 2004 00:57:47 -0000 1.3 @@ -68,7 +68,8 @@ struct __attribute__ ((packed)) sdes_item { enum { END = 0, CNAME = 1, NAME = 2, EMAIL = 3, PHONE = 4, STREET_ADDRESS = - 5, TOOL = 6, NOTE = 7, PRIV = 8 } type:8; + 5, TOOL = 6, NOTE = 7, PRIV = 8 + } type:8; guint8 length; gchar text[1]; } items[1]; /* WARNING: Variable length struct. Do not use the array index for values other than 0 */ Index: rtp_report.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_report.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- a/rtp_report.c 21 Mar 2004 23:31:33 -0000 1.6 +++ b/rtp_report.c 9 Apr 2004 00:57:47 -0000 1.7 @@ -1,73 +1,195 @@ +#include <math.h> +#include <glib/gtypes.h> + #include "rtp_report.h" #include "gstrtpdec.h" +#include "rtp_packet.h" -static guint get_interval_for_report(GstRtpdec* rtpdec); -static gboolean wait(GstRtpdec* rtpdec, guint wait_time); +static void get_interval_for_report (GstRtpdec * rtpdec, GTimeVal * result); -static void send_report(GstRtpdec* rtpdec); +typedef enum +{ CALC_AGAIN_MEMBER_LEFT, CALC_AGAIN_MEMBER_NEW, DO_BYE, + SEND_REPORT } wait_result_t; +{ RTP_NORMAL_MODE, RTP_BYE_MODE } rtp_mode_t; +static wait_result wait (GstRtpdec * rtpdec, const GTimeVal * wait_time, + GTimeVal * elapsed_time_waiting, rtp_mode_t rtp_mode); +static char read_report_thread_message (GstRtpdec * rtpdec); +static void send_report (GstRtpdec * rtpdec); +static void wait_and_send_bye (GstRtpdec * rtpdec); +static void send_bye (GstRtpdec * rtpdec); +static float random_between (float a, float b); +static void get_interval_for_bye (GstRtpdec * rtpdec, GTimeVal * result); gpointer gst_rtpdec_send_report_thread (gpointer ptr) { GstRtpdec *rtpdec = (GstRtpdec *) ptr; - gboolean do_exit; + wait_result_t wait_result; guint wait_time; while (1) { - wait_time = get_interval_for_report (rtpdec); - do_exit = wait (rtpdec, wait_time); - if (do_exit) { + GTimeVal wait_time; + get_interval_for_report (rtpdec, &wait_time); + while (1) { + GTimeVal elapsed_time; + wait_result = wait (rtpdec, &wait_time, &elapsed_time, RTP_NORMAL_MODE); + if (wait_result == CALC_AGAIN_MEMBER_LEFT || + wait_result == CALC_AGAIN_MEMBER_NEW) { + update_wait_time (rtpdec, wait_result, &wait_time, &elpased_time); + continue; + } break; } - send_report (rtpdec); + switch (wait_result) { + case DO_BYE: + send_bye (rtpdec); + return NULL; + case SEND_REPORT: + break; + default: + g_assert_not_reached (); + } } - return NULL; } +static void +update_wait_time (const GstRtpdec * rtpdec, wait_result_t wait_result, + GTimeVal * wait_time, const GTimeVal * elapsed_time) -/* Rules for limiting RTCP control traffic bandwidth - Control bandwidth should be limited to 5 % of the total bandwidth available. - Of that, about 25 % should be reserved for senders (if senders are less than 25 %). - It is recommended that there should be at least 5 seconds between every report generation. - It is also recommended that half of the previous value should be waited at startup, - in order to get the right number of partners before the first packet delivery. - The fixed minimum can be reduced to 360/bandwidth for (a) senders in multicast transmissions, - (b) sender and receiver in unicast transmission. +} - Then, the interval between RTCP packets should be multiplied by a random factor in [0.5, 1.5]. +/* Get the interval of time that we should wait before sending the next RTCP + receiver report. + The result is returned in the timeval argument */ +get_interval_for_report (const GstRtpdec * rtpdec, GTimeVal * timeval) + guint n; + float C; + float Td; /* see rfc 3550 */ + float T; + const float min_interval = 5.0f, min_interval_initial = 2.5; + const float factor_compens = 1.21828; - BYE packets should be sent inmediatly, except with a random delay to avoid a flood by - many simultaneous users. - Timer reconsideration: when + if (rtpdec->initial && !rtpdec->multicast_mode) { + T = 0.0f; + } else { + if (rtpdec->initial) { + Td = min_interval_initial; + } else { + if (rtpdec->num_senders > rtpdec->num_members / 4) { + n = rtpdec->num_senders; + C = ((float) rtpdec->avg_rtcp_size) / rtpdec->rtcp_bw; + } else { + n = rtpdec->num_members; + Td = C * n; + if (Td < min_interval) { + Td = min_interval; + } + T = Td * random_between (0.5f, 1.5f) * factor_compens; + timeval->tv_seconds = floor (t); + timeval->tv_useconds = floor (t * 1000000); - After a BYE packet is received one should not inmediatly remove the entry for that SSRC. - Instead, one should mark the entry for removal. Some delayed packets could arrive causing - the entry to be added. +static float +random_between (float a, float b) + int r; - If no packet has been received from a site in 5 reporting intervals, the site can be regarded - as closed. + r = random (); + return ((float) r) / RAND_MAX * (b - a) + a; - When sending a bye packet: start a timeout, the send the packet. If during the timeout - more BYE packets are received, then increase the timeout accordinly. - Reverse reconsideration: after a bye packet is received, the next packet is delayed - in - -*/ -static guint -get_interval_for_report (GstRtpdec * rtpdec) +/* Wait for the specified time in the wait_time argument. + This waiting can be interrupted by the main thread, because they + commanded us to terminate, or some other order. + wait_result can be + CALC_AGAIN_MEMBER_NEW, + CALC_AGAIN_MEMBER_LEFT : Our RTP session has one new member/one less member. + Thus the time to deliver the next packet has to be recalculated. + DO_BYE: We have been commmanded to terminate. + SEND_REPORT: The time requested has passed. Now we should send a receiver report. + */ +static wait_result +wait (const GstRtpdec * rtpdec, const GTimeVal * wait_time, + const GTimeVal * spent_time, GTimeVal * elapsed_time_waiting, + rtp_mode_t rtp_mode) + struct pollfd fds[1]; + guint wait_time_ms; + fds[1].fd = rtpdec->report_thread_pipe[0]; + fds[1].events = POLLIN; + wait_time_ms = wait_time->tv_seconds * 1000 + wait_time->tv_useconds / 1000; + while (1) { + int retval; + char msg; + retval = poll (fds, 1, wait_time_ms); + if (retval == 0) { + return SEND_REPORT; + g_assert (retval == 1); + msg = read_report_thread_message (rtpdec); + switch (ch) { + case NEW_MEMBER: + if (rtp_mode == RTP_NORMAL_MODE) { + return CALC_AGAIN_MEMBER_NEW; + } + case LEFT_MEMBER: + return CALC_AGAIN_MEMBER_LEFT; + } else { + case PATH_MTU_CHANGED: + /* The last packet was not sent because its size was too large. Send one inmediatly */ + return SEND_REPORT; + case TERMINATE: + g_assert (rtp_mode == RTP_NORMAL_MODE); + return DO_BYE; + abort (); -static gboolean -wait (GstRtpdec * rtpdec, guint wait_time) +static char +read_report_thread_message (const GstRtpdec * rtpdec) + char c; + int retval; + retval = read (rtpdec->report_thread_pipe[0], &c, 1); + g_assert (retval == 1); + return c; static void @@ -75,3 +197,129 @@ +wait_and_send_bye (GstRtpdec * rtpdec) + GTimeVal wait_time; + get_interval_for_bye (rtpdec, &wait_time); + wait_result_t wait_result; + GTimeVal elapsed_time_waiting; + wait_result = + wait (rtpdec, &wait_time, &elapsed_time_waiting, RTP_BYE_MODE); + g_assert (wait_result != CALC_AGAIN_MEMBER_LEFT); + if (wait_result == CALC_AGAIN_MEMBER_NEW) { + update_wait_time (rtpdec, wait_result, &wait_time, &elapsed_time, + RTP_BYE_MODE); + continue; + break; + send_bye (rtpdec); + char *buffer; + guint bufsize; + struct rtcp_recv_report *recv; + struct rtcp_sdes *sdes_cname; + struct rtcp_bye *bye; + guint sdes_size, recv_report_size; + guint num_recp_blocks; + num_recp_blocks = decide_num_recp_blocks (rtpdec); + recv_report_size = size_recv_report (num_recp_blocks); + sdes_size = size_sdes_cname (rtpdec->cname); + bufsize = recv_report_size + sdes_size + sizeof (struct rtcp_bye); + buffer = g_malloc (bufsize); + if (!buffer) { + return; + recv = (struct rtcp_recv_report *) recv; + sdes_cname = (struct rtcp_sdes *) (recv + sizeof (struct rtcp_recv_report)); + bye = (struct rtcp_bye *) (recv + sizeof (struct rtcp_recv_report) + + sdes_size); + init_rtcp_rr (recv, rtpdec->myid, num_recp_blocks); + store_stats_in_rr (rtpdec, recv, num_recp_blocks); + init_rtcp_cname (sdes_cname, rtpdec->myid, rtpdec->cname); + init_rtcp_bye (bye, rtpdec->myid); + send_rtcp (rtpdec, buffer, bufsize); +init_rtcp_common (struct rtcp_common_header *rtcp, packet_type packet_type, + guint16 length) + rtcp->version = 2; + rtcp->padding = 0; + rtcp->num_sources = 1; + rtcp->packet_type = packet_type; + rtcp->length = length; +init_rtcp_rr (struct rtcp_recv_report *recv, guint32 id) + struct reception_block *reception_block; + init_rtcp_common (&recv->common, RECEIVER_REPORT, sizeof (rtcp_recv_report)); + recv->syn_src_rtcp_sender = id; + reception_block = &recv->reception_blocks[0]; + reception_block->identifier = id; +store_stats_in_rr (GstRtpdec * rtpdec, struct rtcp_recv_report *recv, + guint num_recp_blocks) + GCList *link; + for (link = rtpdec->sender_list_rr, i = 0; + link != NULL && i < num_recp_blocks; link = link->next, i++) { + struct sender_info *sender_info; + struct reception_block *reception_block; + sender_info = (struct sender_info *) link->data; + fill_reception_block (recv->reception_blocks[i], sender_info); +fill_reception_block (struct reception_block *reception_block, + const struct sender_info *sender_info) + /* Reminder while coding + struct __attribute__ ((packed)) reception_block { + guint32 identifier; + guint8 fraction_lost_last; + unsigned int cumul_packets_lost:24; + guint32 highest_sequence_number; + guint32 jitter; + guint32 last_timestamp_seen; + guint32 time_since_last_packet; + }; */ + reception_block = recv->reception_blocks[i]; + reception_block->identifier = sender_info->identifier; + if (sender_info->packets_received > 0) { + reception_block->fraction_lost_last = + sender_info->packets_lost * 256 / + (sender_info->packets_received + sender_info->packets_lost); + reception_block->fraction_lost_last = 256; + reception_block->cumul_packets_lost = sender_info->total_packets_lost; + reception_block->highest_sequence_number = sender_info->last_sequence_number; + reception_block->last_timestamp_seen = sender_info->last_ctl_rtptimestamp; + reception_block->time_since_last_packet = sender_info->; + /* Seguir aquí */ Index: socket_fns.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/socket_fns.c,v diff -u -d -r1.7 -r1.8 --- a/socket_fns.c 21 Mar 2004 23:31:33 -0000 1.7 +++ b/socket_fns.c 9 Apr 2004 00:57:47 -0000 1.8 @@ -1,3 +1,6 @@ +/* Open the sockets of an element, close the sockets of an element, + wait for incoming data, and check if a packet is authorized */ #include "socket_fns.h" #include <sys/poll.h> #include <sys/ioctl.h> @@ -20,8 +23,6 @@ }; #endif -static void handle_error_message (const GstRtpdec * dec, int fd); static gboolean try_bind (GstRtpdec * element, in_port_t port, int *socket); static gboolean try_bind_random (GstRtpdec * element, int *socket); @@ -194,16 +195,20 @@ if (element->multicast_mode) { gboolean sucess; sucess = - subscribe_multicast (element, element->data_socket, element->multicast_addr); + subscribe_multicast (element, element->data_socket, + element->multicast_addr); if (!sucess) goto error; - subscribe_multicast (element, element->control_socket, element->multicast_addr); + subscribe_multicast (element, element->control_socket, } else { gst_addr_try_connect (element->data_socket, &element->remote_address, element->remote_data_port); @@ -215,7 +220,9 @@ +#ifdef HAVE_USER_PMTU user_path_mtu (element->control_socket); +#endif return TRUE; error: if (element->control_socket >= 0) { @@ -228,7 +235,7 @@ static gboolean -try_bind (GstRtpdec * element, in_port_t port, int* socket_fd) +try_bind (GstRtpdec * element, in_port_t port, int *socket_fd) struct sockaddr_in6 addr; int i; @@ -280,8 +287,8 @@ ipv6_mreq.ipv6mr_multiaddr = *the_addr; /* FIXME: the user should be able to choose an interface */ ipv6_mreq.ipv6mr_interface = 0; - error = setsockopt (fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, - &ipv6_mreq, sizeof(ipv6_mreq) ); + error = setsockopt (fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, + &ipv6_mreq, sizeof (ipv6_mreq)); if (error == 0) { @@ -289,6 +296,7 @@ return error == 0; +#ifdef HAVE_USER_MTU user_path_mtu (int fd) @@ -299,6 +307,7 @@ int_opt = IPV6_PMTUDISC_WANT; setsockopt (fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &int_opt, sizeof (int_opt)); void gst_rtpdec_close_conn (GstRtpdec * element) --- NEW FILE: todo --- Implement sending of reports (doing it now). Check addr functions. Implement some handlers. Compatibility with systems that only provide IPv4. Sensible names of pads: src_%02d. Do not use the complex ids for pads. Warning: change made: inserting a GCList of sender_info. Update adding/removing sender info so that the list is kept up to date. Warning: added identifier field to sender_info. |
From: Ramon G. F. <ra...@pd...> - 2004-04-09 14:00:50
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Fri Apr 09 2004 07:00:45 PDT Log message: compilation fixes Modified files: rtpdec : gstrtpdec.c gstrtpdec.h rtp_packet.h rtp_report.c socket_fns.c Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c.diff?r1=1.10&r2=1.11 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h.diff?r1=1.10&r2=1.11 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_packet.h.diff?r1=1.3&r2=1.4 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_report.c.diff?r1=1.7&r2=1.8 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/socket_fns.c.diff?r1=1.8&r2=1.9 ====Begin Diffs==== Index: gstrtpdec.c =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- a/gstrtpdec.c 20 Mar 2004 23:33:28 -0000 1.10 +++ b/gstrtpdec.c 9 Apr 2004 14:00:33 -0000 1.11 @@ -153,8 +153,8 @@ rtpdec->clock = NULL; rtpdec->bandwith = 8000; - rtpdec->members = 0; - rtpdec->senders = 0; + rtpdec->num_members = 0; + rtpdec->num_senders = 0; rtpdec->rtcp_bw = rtpdec->bandwith / 20; rtpdec->avg_rtcp_size = 0; Index: gstrtpdec.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h,v --- a/gstrtpdec.h 9 Apr 2004 00:57:47 -0000 1.10 +++ b/gstrtpdec.h 9 Apr 2004 14:00:33 -0000 1.11 @@ -10,6 +10,7 @@ #include "address.h" #include "rtp_packet.h" #include "gstrtphandler.h" +#include "gclist.h" G_BEGIN_DECLS /* #define's don't like whitespacey bits */ @@ -100,8 +101,8 @@ /* Information for scheduling the sending of control info */ guint bandwith; /* in bytes/second */ - guint members; - guint senders; + guint num_members; + guint num_senders; guint rtcp_bw; /* bandwidth for RTCP in bytes per second */ /* we_sent is false */ guint avg_rtcp_size; Index: rtp_packet.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_packet.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- a/rtp_packet.h 9 Apr 2004 00:57:47 -0000 1.3 +++ b/rtp_packet.h 9 Apr 2004 14:00:33 -0000 1.4 @@ -1,3 +1,6 @@ +#ifndef __RTP_PACKET_H__ +#define __RTP_PACKET_H__ 1 + struct __attribute__ ((packed)) rtp_packet { unsigned int version:2; unsigned int padding:1; @@ -16,14 +19,17 @@ guint16 length; }; +typedef enum +{ SENDER_REPORT = 200, RECEIVER_REPORT = 201, SOURCE_DESCRIPTION = 202, + BYE = 203, APP = 204 +} rtcp_packet_type; struct __attribute__ ((packed)) rtcp_common_header { unsigned int num_sources:5; - enum - { SENDER_REPORT = 200, RECEIVER_REPORT = 201, SOURCE_DESCRIPTION = 202, - BYE = 203, APP = 204 - } packet_type:8; + rtcp_packet_type packet_type:8; unsigned int length:16; @@ -87,3 +93,5 @@ guint32 name; char data[1]; +#endif Index: rtp_report.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_report.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- a/rtp_report.c 9 Apr 2004 00:57:47 -0000 1.7 +++ b/rtp_report.c 9 Apr 2004 14:00:33 -0000 1.8 @@ -1,26 +1,39 @@ #include <math.h> #include <glib/gtypes.h> +#include <glib/gmain.h> +#include <sys/poll.h> #include "rtp_report.h" - #include "gstrtpdec.h" +/* Todo list in this file: + implement update_wait_time + implement send_report + finish fill_reception_block + implement get_interval_for_bye + */ -static void get_interval_for_report (GstRtpdec * rtpdec, GTimeVal * result); +static void get_interval_for_report (const GstRtpdec * rtpdec, + GTimeVal * result); typedef enum { CALC_AGAIN_MEMBER_LEFT, CALC_AGAIN_MEMBER_NEW, DO_BYE, - SEND_REPORT } wait_result_t; + SEND_REPORT +} wait_result_t; { RTP_NORMAL_MODE, RTP_BYE_MODE } rtp_mode_t; -static wait_result wait (GstRtpdec * rtpdec, const GTimeVal * wait_time, +static wait_result_t wait (const GstRtpdec * rtpdec, const GTimeVal * wait_time, GTimeVal * elapsed_time_waiting, rtp_mode_t rtp_mode); -static char read_report_thread_message (GstRtpdec * rtpdec); +static void update_wait_time (const GstRtpdec * rtpdec, + wait_result_t wait_result, GTimeVal * wait_time, + const GTimeVal * elapsed_time, rtp_mode_t rtp_mode); +static char read_report_thread_message (const GstRtpdec * rtpdec); static void send_report (GstRtpdec * rtpdec); @@ -30,8 +43,25 @@ static float random_between (float a, float b); -static void get_interval_for_bye (GstRtpdec * rtpdec, GTimeVal * result); +static void get_interval_for_bye (const GstRtpdec * rtpdec, GTimeVal * result); +static void init_rtcp_common (struct rtcp_common_header *rtcp, + rtcp_packet_type packet_type, guint16 length, guint num_sources); +static void init_rtcp_rr (struct rtcp_recv_report *recv, guint32 id, + guint num_reception_blocks); +static void store_stats_in_rr (GstRtpdec * rtpdec, + struct rtcp_recv_report *recv, guint num_recp_blocks); +static void fill_reception_block (struct reception_block *reception_block, + const struct sender_info *sender_info); +/* Main loop of sending RTP reports. Wait until it is time and send + the report */ + gpointer gst_rtpdec_send_report_thread (gpointer ptr) { @@ -49,7 +79,8 @@ wait_result = wait (rtpdec, &wait_time, &elapsed_time, RTP_NORMAL_MODE); if (wait_result == CALC_AGAIN_MEMBER_LEFT || wait_result == CALC_AGAIN_MEMBER_NEW) { - update_wait_time (rtpdec, wait_result, &wait_time, &elpased_time); + update_wait_time (rtpdec, wait_result, &wait_time, &elapsed_time, + RTP_NORMAL_MODE); continue; } break; @@ -67,9 +98,19 @@ } +/* After an event such as someone joined the RTP conference; or one left, + we must update the time before the next report delivery + Arguments: + rtpdec - the main structure. + wait_result - event that causes the change in wait time. + wait_time - new value of wait time. + elapsed_time - time already spent, must be discounted by this function to + the wait time. + rtp_mode - whether we are leaving the conference (RTP_BYE_MODE) or we are + inside it */ static void update_wait_time (const GstRtpdec * rtpdec, wait_result_t wait_result, - GTimeVal * wait_time, const GTimeVal * elapsed_time) + GTimeVal * wait_time, const GTimeVal * elapsed_time, rtp_mode_t rtp_mode) @@ -80,9 +121,10 @@ get_interval_for_report (const GstRtpdec * rtpdec, GTimeVal * timeval) + /* Short variables names choosen to match rfc3550 */ guint n; float C; - float Td; /* see rfc 3550 */ + float Td; float T; const float min_interval = 5.0f, min_interval_initial = 2.5; const float factor_compens = 1.21828; @@ -107,10 +149,11 @@ } } T = Td * random_between (0.5f, 1.5f) * factor_compens; - timeval->tv_seconds = floor (t); - timeval->tv_useconds = floor (t * 1000000); + timeval->tv_sec = floor (T); + timeval->tv_usec = floor (T * 1000000); +/* Return a random number uniformly distributed between a and b */ static float random_between (float a, float b) @@ -130,57 +173,63 @@ Thus the time to deliver the next packet has to be recalculated. DO_BYE: We have been commmanded to terminate. SEND_REPORT: The time requested has passed. Now we should send a receiver report. + rtp_mode can be RTP_NORMAL_MODE if we are in the conference, or + RTP_BYE_MODE if we are leaving the conference (and deciding how + long we should wait before sending the RTP BYE message) */ -static wait_result +static wait_result_t wait (const GstRtpdec * rtpdec, const GTimeVal * wait_time, - const GTimeVal * spent_time, GTimeVal * elapsed_time_waiting, - rtp_mode_t rtp_mode) + GTimeVal * elapsed_time_waiting, rtp_mode_t rtp_mode) struct pollfd fds[1]; guint wait_time_ms; + int retval; + char msg; + GTimeVal time_before; fds[1].fd = rtpdec->report_thread_pipe[0]; fds[1].events = POLLIN; - wait_time_ms = wait_time->tv_seconds * 1000 + wait_time->tv_useconds / 1000; - while (1) { - int retval; - char msg; - retval = poll (fds, 1, wait_time_ms); - if (retval == 0) { + wait_time_ms = wait_time->tv_sec * 1000 + wait_time->tv_usec / 1000; + g_get_current_time (&time_before); + retval = poll (fds, 1, wait_time_ms); + g_get_current_time (elapsed_time_waiting); + sub_gtimeval (elapsed_time_waiting, &time_before); + if (retval == 0) { + return SEND_REPORT; + } + g_assert (retval == 1); + msg = read_report_thread_message (rtpdec); + switch (msg) { + case NEW_MEMBER: + if (rtp_mode == RTP_NORMAL_MODE) { + return CALC_AGAIN_MEMBER_NEW; + } + break; + case LEFT_MEMBER: + return CALC_AGAIN_MEMBER_LEFT; + } else { + case PATH_MTU_CHANGED: + /* The last packet was not sent because its size was too large. Send one inmediatly */ return SEND_REPORT; - } - g_assert (retval == 1); - msg = read_report_thread_message (rtpdec); - switch (ch) { - case NEW_MEMBER: - if (rtp_mode == RTP_NORMAL_MODE) { - return CALC_AGAIN_MEMBER_NEW; - } - break; - case LEFT_MEMBER: - return CALC_AGAIN_MEMBER_LEFT; - } else { - case PATH_MTU_CHANGED: - /* The last packet was not sent because its size was too large. Send one inmediatly */ - return SEND_REPORT; - case TERMINATE: - g_assert (rtp_mode == RTP_NORMAL_MODE); - return DO_BYE; - default: - abort (); + case TERMINATE: + g_assert (rtp_mode == RTP_NORMAL_MODE); + return DO_BYE; + default: + g_assert_not_reached (); +/* Read any message that the main thread of GstRtpdec sent us */ static char read_report_thread_message (const GstRtpdec * rtpdec) @@ -192,13 +241,17 @@ return c; +/* Send a control report with current statistics */ send_report (GstRtpdec * rtpdec) +/* Send a bye message to leave the conference. + But before we should wait some time, otherwise + many people leaving at the same time would collapse + the server */ wait_and_send_bye (GstRtpdec * rtpdec) @@ -213,7 +266,7 @@ wait (rtpdec, &wait_time, &elapsed_time_waiting, RTP_BYE_MODE); g_assert (wait_result != CALC_AGAIN_MEMBER_LEFT); if (wait_result == CALC_AGAIN_MEMBER_NEW) { - update_wait_time (rtpdec, wait_result, &wait_time, &elapsed_time, + update_wait_time (rtpdec, wait_result, &wait_time, &elapsed_time_waiting, RTP_BYE_MODE); continue; } else { @@ -223,8 +276,15 @@ send_bye (rtpdec); -static void send_bye (GstRtpdec * rtpdec); +/* Evaluate the time that we should wait before sending a BYE message */ +static void +get_interval_for_bye (const GstRtpdec * rtpdec, GTimeVal * result) +{ +} +/* Send now a BYE message to leave the RTP conference */ +send_bye (GstRtpdec * rtpdec) char *buffer; guint bufsize; @@ -253,34 +313,42 @@ send_rtcp (rtpdec, buffer, bufsize); +/* Code to setup the data structures of a RTCP message */ +/* Init the common part of a RTCP packet */ -init_rtcp_common (struct rtcp_common_header *rtcp, packet_type packet_type, - guint16 length) +init_rtcp_common (struct rtcp_common_header *rtcp, rtcp_packet_type packet_type, + guint16 length, guint num_sources) rtcp->version = 2; rtcp->padding = 0; - rtcp->num_sources = 1; + rtcp->num_sources = num_sources; rtcp->packet_type = packet_type; rtcp->length = length; +/* Init a RTCP receiver record */ -init_rtcp_rr (struct rtcp_recv_report *recv, guint32 id) +init_rtcp_rr (struct rtcp_recv_report *recv, guint32 id, + guint num_reception_blocks) struct reception_block *reception_block; - init_rtcp_common (&recv->common, RECEIVER_REPORT, sizeof (rtcp_recv_report)); - recv->syn_src_rtcp_sender = id; + init_rtcp_common (&recv->common, RECEIVER_REPORT, + sizeof (struct rtcp_recv_report), num_reception_blocks); + recv->sync_src_rtcp_sender = id; reception_block = &recv->reception_blocks[0]; - reception_block->identifier = id; +/* Store statistics in a RTCP receiver record */ store_stats_in_rr (GstRtpdec * rtpdec, struct rtcp_recv_report *recv, guint num_recp_blocks) GCList *link; + guint i; for (link = rtpdec->sender_list_rr, i = 0; link != NULL && i < num_recp_blocks; link = link->next, i++) { @@ -288,7 +356,7 @@ struct reception_block *reception_block; sender_info = (struct sender_info *) link->data; - fill_reception_block (recv->reception_blocks[i], sender_info); + fill_reception_block (&recv->reception_blocks[i], sender_info); @@ -308,18 +376,17 @@ }; */ - reception_block = recv->reception_blocks[i]; reception_block->identifier = sender_info->identifier; - if (sender_info->packets_received > 0) { + if ((sender_info->packets_received + sender_info->packets_lost) > 0) { reception_block->fraction_lost_last = sender_info->packets_lost * 256 / (sender_info->packets_received + sender_info->packets_lost); } else { - reception_block->fraction_lost_last = 256; + reception_block->fraction_lost_last = 0; reception_block->cumul_packets_lost = sender_info->total_packets_lost; reception_block->highest_sequence_number = sender_info->last_sequence_number; reception_block->last_timestamp_seen = sender_info->last_ctl_rtptimestamp; - reception_block->time_since_last_packet = sender_info->; + /* reception_block->time_since_last_packet = sender_info->; */ /* Seguir aquí */ Index: socket_fns.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/socket_fns.c,v retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- a/socket_fns.c 9 Apr 2004 00:57:47 -0000 1.8 +++ b/socket_fns.c 9 Apr 2004 14:00:33 -0000 1.9 @@ -10,6 +10,12 @@ #define HAVE_USER_PMTU #ifdef HAVE_USER_PMTU +/* MTU controlled by the user is used only for + the control packets. That means, the UDP protocol + sends our packets as-is, without fragmenting. If they + are too large, we are warned, and the next time we + send smaller packets. */ #include <errno.h> struct sock_extended_err @@ -296,7 +302,7 @@ return error == 0; -#ifdef HAVE_USER_MTU +#ifdef HAVE_USER_PMTU user_path_mtu (int fd) |
From: Ramon G. F. <ra...@pd...> - 2004-04-09 16:48:16
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Fri Apr 09 2004 09:48:09 PDT Log message: continue with report delivery Modified files: rtpdec : rtp_packet.h rtp_report.c todo Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_packet.h.diff?r1=1.4&r2=1.5 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_report.c.diff?r1=1.8&r2=1.9 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/todo.diff?r1=1.1&r2=1.2 ====Begin Diffs==== Index: rtp_packet.h =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_packet.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- a/rtp_packet.h 9 Apr 2004 14:00:33 -0000 1.4 +++ b/rtp_packet.h 9 Apr 2004 16:47:57 -0000 1.5 @@ -39,8 +39,8 @@ unsigned int cumul_packets_lost:24; guint32 highest_sequence_number; guint32 jitter; - guint32 last_timestamp_seen; - guint32 time_since_last_packet; + guint32 last_ntp_timestamp_seen_sr; + guint32 time_since_last_sr_packet; }; struct __attribute__ ((packed)) ntptime { Index: rtp_report.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_report.c,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- a/rtp_report.c 9 Apr 2004 14:00:33 -0000 1.8 +++ b/rtp_report.c 9 Apr 2004 16:47:57 -0000 1.9 @@ -1,3 +1,10 @@ +/* The code of this file sends RTP control reports to the partners of the conference It runs in a separate thread. It evaluates the time between reports according to + RFC 3550, section 6.3, and then it build the RTCP packets and sends them. + In addition, it listens for messages from the main thread of this RTP decoder, + sent to the pipe report_thread_pipe. That messages tell us to adjust the spacing + between control messages because of someone entering or leaving the conference. Or + tell us to finish */ + #include <math.h> #include <glib/gtypes.h> #include <glib/gmain.h> @@ -10,8 +17,10 @@ /* Todo list in this file: implement update_wait_time implement send_report - finish fill_reception_block implement get_interval_for_bye + implement decide_num_recp_blocks + take care of races. The main thread removing a sender from the list, + while we are building the RTCP message with the list of senders. */ @@ -45,6 +54,8 @@ static void get_interval_for_bye (const GstRtpdec * rtpdec, GTimeVal * result); +static guint decide_num_recp_blocks (const GstRtpdec * rtpdec); static void init_rtcp_common (struct rtcp_common_header *rtcp, rtcp_packet_type packet_type, guint16 length, guint num_sources); @@ -57,7 +68,9 @@ static void fill_reception_block (struct reception_block *reception_block, const struct sender_info *sender_info); +static guint32 middle_bits(const struct ntptime time); +static guint32 current_time_sub_ntptime(struct ntptime time); /* Main loop of sending RTP reports. Wait until it is time and send the report */ @@ -306,7 +319,6 @@ sdes_cname = (struct rtcp_sdes *) (recv + sizeof (struct rtcp_recv_report)); bye = (struct rtcp_bye *) (recv + sizeof (struct rtcp_recv_report) + sdes_size); - init_rtcp_rr (recv, rtpdec->myid, num_recp_blocks); store_stats_in_rr (rtpdec, recv, num_recp_blocks); init_rtcp_cname (sdes_cname, rtpdec->myid, rtpdec->cname); init_rtcp_bye (bye, rtpdec->myid); @@ -316,7 +328,7 @@ /* Code to setup the data structures of a RTCP message */ -/* Init the common part of a RTCP packet */ +/* Init the common part of any RTCP packet */ static void init_rtcp_common (struct rtcp_common_header *rtcp, rtcp_packet_type packet_type, guint16 length, guint num_sources) @@ -328,54 +340,72 @@ rtcp->length = length; } -/* Init a RTCP receiver record */ +/* Initialize the fields of a RTCP receiver record */ init_rtcp_rr (struct rtcp_recv_report *recv, guint32 id, guint num_reception_blocks) { - struct reception_block *reception_block; - init_rtcp_common (&recv->common, RECEIVER_REPORT, sizeof (struct rtcp_recv_report), num_reception_blocks); recv->sync_src_rtcp_sender = id; - reception_block = &recv->reception_blocks[0]; +} +static guint +decide_num_recp_blocks(const GstRtpdec * rtpdec) +{ /* Store statistics in a RTCP receiver record */ -store_stats_in_rr (GstRtpdec * rtpdec, struct rtcp_recv_report *recv, +store_stats_in_rr (GstRtpdec * rtpdec, struct rtcp_recv_report *first_recv, guint num_recp_blocks) GCList *link; - guint i; + guint num_recp_block; - for (link = rtpdec->sender_list_rr, i = 0; - link != NULL && i < num_recp_blocks; link = link->next, i++) { - struct sender_info *sender_info; - struct reception_block *reception_block; + struct rtcp_recv_report *current_recv; - sender_info = (struct sender_info *) link->data; - fill_reception_block (&recv->reception_blocks[i], sender_info); + for (current_recv = first_recv, num_recp_block = 0, link = rtpdec->sender_list_rr; + num_recp_block < num_recp_blocks; ) { + guint num_recp_blocks_here; + guint num_recp_blocks_remain; + guint this_record_size; + guint num_recp_block_here; + num_recp_blocks_remain = num_recp_blocks - num_recp_block; + if (num_recp_blocks_remain > 31) { + num_recp_blocks_here = 31; + } else { + num_recp_blocks_here = num_recp_blocks_remain; + } + init_rtcp_rr (current_recv, rtpdec->myid, num_recp_blocks_here); + for (num_recp_block_here = 0; + link != NULL && num_recp_block_here < num_recp_blocks_here; + link = link->next, num_recp_blocks++) { + struct sender_info *sender_info; + struct reception_block *reception_block; + + sender_info = (struct sender_info *) link->data; + reception_block = ¤t_recv->reception_blocks[num_recp_block_here]; + fill_reception_block (¤t_recv->reception_blocks[num_recp_block_here], sender_info); + this_record_size = sizeof(struct rtcp_recv_report) + + sizeof(struct reception_block)*(num_recp_blocks_here - 1); + /* Round this_record_size to the next multiple of 4 */ + this_record_size = ((this_record_size + 3)/4)*4; + current_recv = (struct rtcp_recv_report*) + (((char*) current_recv) + this_record_size); + num_recp_block = num_recp_block + num_recp_blocks_here; } fill_reception_block (struct reception_block *reception_block, const struct sender_info *sender_info) - /* Reminder while coding - struct __attribute__ ((packed)) reception_block { - guint32 identifier; - guint8 fraction_lost_last; - unsigned int cumul_packets_lost:24; - guint32 highest_sequence_number; - guint32 jitter; - guint32 last_timestamp_seen; - guint32 time_since_last_packet; - }; */ reception_block->identifier = sender_info->identifier; if ((sender_info->packets_received + sender_info->packets_lost) > 0) { reception_block->fraction_lost_last = @@ -386,7 +416,40 @@ reception_block->cumul_packets_lost = sender_info->total_packets_lost; reception_block->highest_sequence_number = sender_info->last_sequence_number; - reception_block->last_timestamp_seen = sender_info->last_ctl_rtptimestamp; - /* reception_block->time_since_last_packet = sender_info->; */ - /* Seguir aquí */ + reception_block->jitter = sender_info->jitter; + reception_block->last_ntp_timestamp_seen_sr = middle_bits(sender_info->last_ctl_ntptime); + reception_block->time_since_last_sr_packet = + current_time_sub_ntptime(sender_info->last_ctl_ntptime); +static guint32 middle_bits(const struct ntptime time) + return (time.integer << 16) + (time.frac >> 16); +static guint32 current_time_sub_ntptime(struct ntptime time) + GTimeVal current_time; + guint seconds, frac_current, frac; + if (time.integer == 0 && time.frac == 0) { + return 0; + } + g_get_current_time(¤t_time); + if (current_time.tv_sec < time.integer) { + } else { + seconds = current_time.tv_sec - time.integer; + /* Avoid 1 << 32 /1000000 that would cause overflow */ + frac_current = current_time.tv_usec*((1 << 31)/500000); + if (frac_current < time.frac) { + if (seconds == 0) { + return 0; + seconds = seconds - 1; + } + /* Actually, if frac_current < time.frac, + frac = 2^32 + frac_current - time.frac. Overflow achieves this result */ + frac = frac_current - time.frac; + return (seconds << 16) + (frac >> 16); Index: todo RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/todo,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- a/todo 9 Apr 2004 00:57:47 -0000 1.1 +++ b/todo 9 Apr 2004 16:47:57 -0000 1.2 @@ -12,3 +12,6 @@ adding/removing sender info so that the list is kept up to date. Warning: added identifier field to sender_info. +Think about races. While the reporting thread is preparing the report, +the other thread removes an entry because of a BYE message. \ No newline at end of file |
From: <ra...@fr...> - 2004-08-09 19:07:51
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Mon Aug 09 2004 12:07:49 PDT Log message: rtpdec.c: missing NULL terminator in call to gst_structure_new(). Thanks to __tim Modified files: rtpdec : rtpdec.c Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtpdec.c.diff?r1=1.6&r2=1.7 ====Begin Diffs==== Index: rtpdec.c =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtpdec.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- rtpdec.c 14 May 2004 10:06:29 -0000 1.6 +++ rtpdec.c 9 Aug 2004 19:07:37 -0000 1.7 @@ -91,7 +91,7 @@ g_value_init (&num_channels, G_TYPE_UINT); g_value_set_uint (&num_channels, fixed_payloads[i].sample_rate); payload_desc = gst_structure_new (fixed_payloads[i].name, - "sample-rate", sample_rate, "num-channels", num_channels); + "sample-rate", sample_rate, "num-channels", num_channels, NULL); number = g_new (int, 1); *number = 0; |
From: <ra...@fr...> - 2004-08-13 10:31:06
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Fri Aug 13 2004 03:31:05 PDT Log message: Implemented update_wait_time, add missing gclist.h Modified files: rtpdec : Makefile gstrtpdec.h rtp_report.c todo Added files: rtpdec : gclist.h Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/Makefile.diff?r1=1.3&r2=1.4 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gclist.h?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h.diff?r1=1.11&r2=1.12 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_report.c.diff?r1=1.10&r2=1.11 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/todo.diff?r1=1.2&r2=1.3 ====Begin Diffs==== Index: Makefile =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/Makefile,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- Makefile 21 Mar 2004 23:31:33 -0000 1.3 +++ Makefile 13 Aug 2004 10:30:53 -0000 1.4 @@ -1,4 +1,4 @@ -CFLAGS=$(shell pkg-config --cflags gstreamer-0.7) -DGST_PACKAGE='"GStreamer"' -DGST_ORIGIN='"http://gstreamer.net"' -DVERSION='"0.0"' -Werror +CFLAGS=$(shell pkg-config --cflags gstreamer-0.8) -DGST_PACKAGE='"GStreamer"' -DGST_ORIGIN='"http://gstreamer.net"' -DVERSION='"0.0"' -Werror check: gstrtpdec.o rtpdec.o rtp_report.o socket_fns.o --- NEW FILE: gclist.h --- #include <glib.h> struct _GCList { gpointer data; struct _GCList* next; }; typedef struct _GCList GCList; Index: gstrtpdec.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.h,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- gstrtpdec.h 9 Apr 2004 14:00:33 -0000 1.11 +++ gstrtpdec.h 13 Aug 2004 10:30:53 -0000 1.12 @@ -101,7 +101,7 @@ /* Information for scheduling the sending of control info */ guint bandwith; /* in bytes/second */ - guint num_members; + guint num_members, new_num_members; guint num_senders; guint rtcp_bw; /* bandwidth for RTCP in bytes per second */ /* we_sent is false */ Index: rtp_report.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_report.c,v retrieving revision 1.10 diff -u -d -r1.10 -r1.11 --- rtp_report.c 9 Aug 2004 16:46:48 -0000 1.10 +++ rtp_report.c 13 Aug 2004 10:30:53 -0000 1.11 @@ -16,7 +16,6 @@ #include "rtp_packet.h" /* Todo list in this file: - implement update_wait_time implement send_report implement get_interval_for_bye implement decide_num_recp_blocks @@ -73,6 +72,14 @@ static guint32 current_time_sub_ntptime(struct ntptime time); +static void sub_gtimeval(GTimeVal* a, const GTimeVal* b); + +static float timeval_to_float(const GTimeVal* a); +static float_to_timeval(float f, GTimeVal* a); /* Main loop of sending RTP reports. Wait until it is time and send the report */ @@ -127,9 +134,14 @@ update_wait_time (const GstRtpdec * rtpdec, wait_result_t wait_result, GTimeVal * wait_time, const GTimeVal * elapsed_time, rtp_mode_t rtp_mode) { - + sub_gtimeval(wait_time, elapsed_time); + float wait_float; + wait_float = timeval_to_float(wait_time); + wait_float *= ((float)rtpdec->new_num_members)/rtpdec->num_members; + float_to_timeval(wait_float, wait_time); } /* Get the interval of time that we should wait before sending the next RTCP receiver report. The result is returned in the timeval argument */ @@ -138,11 +150,11 @@ /* Short variables names choosen to match rfc3550 */ guint n; - float C; - float Td; - float T; - const float min_interval = 5.0f, min_interval_initial = 2.5; - const float factor_compens = 1.21828; + float C; /* average period if there were only one participant */ + float Td; /* average period */ + float T; /*actual time that we have to wait */ + const float min_interval = 5.0f, min_interval_initial = 2.5f; + const float factor_compens = 1.21828f; if (rtpdec->initial && !rtpdec->multicast_mode) { T = 0.0f; @@ -162,8 +174,8 @@ Td = min_interval; } } + T = Td * random_between (0.5f, 1.5f) * factor_compens; } - T = Td * random_between (0.5f, 1.5f) * factor_compens; timeval->tv_sec = floor (T); timeval->tv_usec = floor (T * 1000000); @@ -260,7 +272,7 @@ static void send_report (GstRtpdec * rtpdec) + /* FIXME: implement */ /* Send a bye message to leave the conference. @@ -295,6 +307,7 @@ get_interval_for_bye (const GstRtpdec * rtpdec, GTimeVal * result) /* Send now a BYE message to leave the RTP conference */ @@ -356,6 +369,7 @@ static guint decide_num_recp_blocks(const GstRtpdec * rtpdec) /* Store statistics in a RTCP receiver record */ @@ -455,3 +469,34 @@ return (seconds << 16) + (frac >> 16); +/* FIXME: this should be in a separate library */ +static void sub_gtimeval(GTimeVal* a, const GTimeVal* b) +{ + if (a->tv_sec < b->tv_sec || + (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec)) { + g_warning("sub_gtimeval: negative result"); + a->tv_sec = 0; + a->tv_usec = 0; + return; + } + a->tv_sec -= b->tv_sec; + a->tv_usec -= b->tv_usec; + if (a->tv_usec < 0) { + a->tv_sec--; + a->tv_usec += 1000000; +} +static float timeval_to_float(const GTimeVal* a) + return a->tv_sec + ((float) a->tv_usec)/1000000; +static float_to_timeval(float f, GTimeVal* a) + a->tv_sec = floor(f); + a->tv_usec = (f - floor(f))*1000000; Index: todo RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/todo,v retrieving revision 1.2 diff -u -d -r1.2 -r1.3 --- todo 9 Apr 2004 16:47:57 -0000 1.2 +++ todo 13 Aug 2004 10:30:53 -0000 1.3 @@ -1,3 +1,14 @@ +* Short term +Finish rtp_report.c: send_report. +Update rtpdec.c, so that it sends a message when a new receiver is got or dropped. +Remember, now we have new_num_members in GstRtpdec, that must be used for this purpose. +Implement gclist.c and actually update GCLists. +* Long term Implement sending of reports (doing it now). Check addr functions. |
From: <ra...@fr...> - 2004-08-19 22:53:06
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Thu Aug 19 2004 15:53:03 PDT Log message: rtp_report.c: implemented some missing functions Modified files: rtpdec : Makefile rtp_report.c Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/Makefile.diff?r1=1.4&r2=1.5 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_report.c.diff?r1=1.11&r2=1.12 ====Begin Diffs==== Index: Makefile =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/Makefile,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- Makefile 13 Aug 2004 10:30:53 -0000 1.4 +++ Makefile 19 Aug 2004 22:52:51 -0000 1.5 @@ -1,4 +1,4 @@ -CFLAGS=$(shell pkg-config --cflags gstreamer-0.8) -DGST_PACKAGE='"GStreamer"' -DGST_ORIGIN='"http://gstreamer.net"' -DVERSION='"0.0"' -Werror +CFLAGS=$(shell pkg-config --cflags gstreamer-0.8) -DGST_PACKAGE='"GStreamer"' -DGST_ORIGIN='"http://gstreamer.net"' -DVERSION='"0.0"' -Wall -Werror check: gstrtpdec.o rtpdec.o rtp_report.o socket_fns.o Index: rtp_report.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_report.c,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- rtp_report.c 13 Aug 2004 10:30:53 -0000 1.11 +++ rtp_report.c 19 Aug 2004 22:52:51 -0000 1.12 @@ -10,13 +10,13 @@ #include <glib/gtypes.h> #include <glib/gmain.h> #include <sys/poll.h> +#include <unistd.h> #include "rtp_report.h" #include "gstrtpdec.h" #include "rtp_packet.h" /* Todo list in this file: - implement send_report implement get_interval_for_bye implement decide_num_recp_blocks take care of races. The main thread removing a sender from the list, @@ -40,15 +40,17 @@ static void update_wait_time (const GstRtpdec * rtpdec, wait_result_t wait_result, GTimeVal * wait_time, - const GTimeVal * elapsed_time, rtp_mode_t rtp_mode); + const GTimeVal * elapsed_time); static char read_report_thread_message (const GstRtpdec * rtpdec); -static void send_report (GstRtpdec * rtpdec); +static void send_report (GstRtpdec * rtpdec, gboolean do_bye); static void wait_and_send_bye (GstRtpdec * rtpdec); -static void send_bye (GstRtpdec * rtpdec); +static void update_bye_wait_time (const GstRtpdec * rtpdec, + guint* num_bye_senders, GTimeVal * wait_time, static float random_between (float a, float b); @@ -76,7 +78,7 @@ static float timeval_to_float(const GTimeVal* a); -static float_to_timeval(float f, GTimeVal* a); +static void float_to_timeval(float f, GTimeVal* a); @@ -88,7 +90,6 @@ { GstRtpdec *rtpdec = (GstRtpdec *) ptr; wait_result_t wait_result; - guint wait_time; while (1) { GTimeVal wait_time; @@ -100,18 +101,17 @@ wait_result = wait (rtpdec, &wait_time, &elapsed_time, RTP_NORMAL_MODE); if (wait_result == CALC_AGAIN_MEMBER_LEFT || wait_result == CALC_AGAIN_MEMBER_NEW) { - update_wait_time (rtpdec, wait_result, &wait_time, &elapsed_time, - RTP_NORMAL_MODE); + update_wait_time (rtpdec, wait_result, &wait_time, &elapsed_time); continue; } break; } switch (wait_result) { case DO_BYE: - send_bye (rtpdec); + send_report (rtpdec, TRUE); return NULL; case SEND_REPORT: - send_report(rtpdec); + wait_and_send_bye(rtpdec); break; default: g_assert_not_reached (); @@ -127,15 +127,14 @@ wait_result - event that causes the change in wait time. wait_time - new value of wait time. elapsed_time - time already spent, must be discounted by this function to - the wait time. - rtp_mode - whether we are leaving the conference (RTP_BYE_MODE) or we are - inside it */ + the wait time. */ + static void update_wait_time (const GstRtpdec * rtpdec, wait_result_t wait_result, - GTimeVal * wait_time, const GTimeVal * elapsed_time, rtp_mode_t rtp_mode) + GTimeVal * wait_time, const GTimeVal * elapsed_time) - sub_gtimeval(wait_time, elapsed_time); float wait_float; + sub_gtimeval(wait_time, elapsed_time); wait_float = timeval_to_float(wait_time); wait_float *= ((float)rtpdec->new_num_members)/rtpdec->num_members; float_to_timeval(wait_float, wait_time); @@ -220,39 +219,40 @@ fds[1].events = POLLIN; wait_time_ms = wait_time->tv_sec * 1000 + wait_time->tv_usec / 1000; g_get_current_time (&time_before); - retval = poll (fds, 1, wait_time_ms); - g_get_current_time (elapsed_time_waiting); - sub_gtimeval (elapsed_time_waiting, &time_before); - if (retval == 0) { - return SEND_REPORT; - } - g_assert (retval == 1); - msg = read_report_thread_message (rtpdec); - switch (msg) { - case NEW_MEMBER: - if (rtp_mode == RTP_NORMAL_MODE) { - return CALC_AGAIN_MEMBER_NEW; - } - break; - case LEFT_MEMBER: - return CALC_AGAIN_MEMBER_LEFT; - } else { - case PATH_MTU_CHANGED: - /* The last packet was not sent because its size was too large. Send one inmediatly */ + while (1) { + retval = poll (fds, 1, wait_time_ms); + g_get_current_time (elapsed_time_waiting); + sub_gtimeval (elapsed_time_waiting, &time_before); + if (retval == 0) { return SEND_REPORT; - case TERMINATE: - g_assert (rtp_mode == RTP_NORMAL_MODE); - return DO_BYE; - default: - g_assert_not_reached (); + } + g_assert (retval == 1); + msg = read_report_thread_message (rtpdec); + switch (msg) { + case NEW_MEMBER: + if (rtp_mode == RTP_NORMAL_MODE) { + return CALC_AGAIN_MEMBER_NEW; + } + break; + case LEFT_MEMBER: + return CALC_AGAIN_MEMBER_LEFT; + } else { + case PATH_MTU_CHANGED: + /* The last packet was not sent because its size was too large. Send one inmediatly */ + return SEND_REPORT; + case TERMINATE: + g_assert (rtp_mode == RTP_NORMAL_MODE); + return DO_BYE; + default: + g_assert_not_reached (); } - } @@ -269,12 +269,43 @@ /* Send a control report with current statistics */ -send_report (GstRtpdec * rtpdec) +send_report (GstRtpdec * rtpdec, gboolean do_bye) - /* FIXME: implement */ + char *buffer; + guint bufsize; + struct rtcp_recv_report *recv; + struct rtcp_sdes *sdes_cname; + guint sdes_size, recv_report_size; + guint num_recp_blocks; + num_recp_blocks = decide_num_recp_blocks (rtpdec); + recv_report_size = size_recv_report (num_recp_blocks); + sdes_size = size_sdes_cname (rtpdec->cname); + bufsize = recv_report_size + sdes_size; + if (do_bye) { + bufsize += sizeof (struct rtcp_bye); + } + buffer = g_malloc (bufsize); + if (!buffer) { + return; + recv = (struct rtcp_recv_report *) recv; + sdes_cname = (struct rtcp_sdes *) (recv + sizeof (struct rtcp_recv_report)); + store_stats_in_rr (rtpdec, recv, num_recp_blocks); + init_rtcp_cname (sdes_cname, rtpdec->myid, rtpdec->cname); + struct rtcp_bye *bye; + bye = (struct rtcp_bye *) (recv + sizeof (struct rtcp_recv_report) + + sdes_size); + init_rtcp_bye (bye, rtpdec->myid); + send_rtcp (rtpdec, buffer, bufsize); /* Send a bye message to leave the conference. But before we should wait some time, otherwise many people leaving at the same time would collapse @@ -287,59 +318,50 @@ get_interval_for_bye (rtpdec, &wait_time); wait_result_t wait_result; + guint num_bye_senders; GTimeVal elapsed_time_waiting; + num_bye_senders = 1; wait_result = - wait (rtpdec, &wait_time, &elapsed_time_waiting, RTP_BYE_MODE); + wait (rtpdec, &wait_time, &elapsed_time_waiting, RTP_BYE_MODE); g_assert (wait_result != CALC_AGAIN_MEMBER_LEFT); if (wait_result == CALC_AGAIN_MEMBER_NEW) { - update_wait_time (rtpdec, wait_result, &wait_time, &elapsed_time_waiting, - RTP_BYE_MODE); + update_bye_wait_time (rtpdec, &num_bye_senders, &wait_time, &elapsed_time_waiting); continue; } else { - send_bye (rtpdec); + send_report(rtpdec, TRUE); /* Evaluate the time that we should wait before sending a BYE message */ get_interval_for_bye (const GstRtpdec * rtpdec, GTimeVal * result) -} -/* Send now a BYE message to leave the RTP conference */ -static void -send_bye (GstRtpdec * rtpdec) -{ - char *buffer; - guint bufsize; - struct rtcp_recv_report *recv; - struct rtcp_sdes *sdes_cname; - struct rtcp_bye *bye; - guint sdes_size, recv_report_size; - guint num_recp_blocks; - num_recp_blocks = decide_num_recp_blocks (rtpdec); - recv_report_size = size_recv_report (num_recp_blocks); - sdes_size = size_sdes_cname (rtpdec->cname); - bufsize = recv_report_size + sdes_size + sizeof (struct rtcp_bye); - buffer = g_malloc (bufsize); - if (!buffer) { + if (!rtpdec->multicast_mode) { + result->tv_sec = 0; + result->tv_usec = 0; return; + } else { + float time; + const float min_interval = 5.0f; + const float factor_compens = 1.21828f; + time = min_interval*random_between(0.5f, 1.5f)*factor_compens; + result->tv_sec = floor(time); + result->tv_usec = time - floor(time) * 1000000; - recv = (struct rtcp_recv_report *) recv; - sdes_cname = (struct rtcp_sdes *) (recv + sizeof (struct rtcp_recv_report)); - bye = (struct rtcp_bye *) (recv + sizeof (struct rtcp_recv_report) + - sdes_size); - store_stats_in_rr (rtpdec, recv, num_recp_blocks); - init_rtcp_cname (sdes_cname, rtpdec->myid, rtpdec->cname); - init_rtcp_bye (bye, rtpdec->myid); - send_rtcp (rtpdec, buffer, bufsize); +static void +update_bye_wait_time(const GstRtpdec* rtpdec, guint* num_bye_senders, + GTimeVal* wait_time, const GTimeVal* elapsed_time_waiting) +{ + float wait_float; + sub_gtimeval(wait_time, elapsed_time_waiting); + wait_float = timeval_to_float(wait_time); + wait_float = wait_float*(*num_bye_senders + 1)/(*num_bye_senders); + *num_bye_senders++; +} /* Code to setup the data structures of a RTCP message */ @@ -495,8 +517,9 @@ return a->tv_sec + ((float) a->tv_usec)/1000000; -static float_to_timeval(float f, GTimeVal* a) +static void float_to_timeval(float f, GTimeVal* a) a->tv_sec = floor(f); a->tv_usec = (f - floor(f))*1000000; |
From: <ra...@fr...> - 2004-08-19 23:09:23
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Thu Aug 19 2004 16:09:20 PDT Log message: rtp_report.c: compilation fixes; added empty definitions for missing functions Modified files: rtpdec : rtp_report.c Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_report.c.diff?r1=1.12&r2=1.13 ====Begin Diffs==== Index: rtp_report.c =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_report.c,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- rtp_report.c 19 Aug 2004 22:52:51 -0000 1.12 +++ rtp_report.c 19 Aug 2004 23:09:08 -0000 1.13 @@ -67,9 +67,19 @@ static void store_stats_in_rr (GstRtpdec * rtpdec, struct rtcp_recv_report *recv, guint num_recp_blocks); +static guint size_recv_report(guint num_recp_blocks); + +static guint size_sdes_cname(GString* cname); +static void init_rtcp_cname(struct rtcp_sdes* sdes, guint32 myid, GString* cname); static void fill_reception_block (struct reception_block *reception_block, const struct sender_info *sender_info); +static void init_rtcp_bye(struct rtcp_bye* rtcp_bye, guint32 myid); +static void send_rtcp(const GstRtpdec* rtpdec, const char* buffer, guint32 bufsize); static guint32 middle_bits(const struct ntptime time); static guint32 current_time_sub_ntptime(struct ntptime time); @@ -391,6 +401,7 @@ static guint decide_num_recp_blocks(const GstRtpdec * rtpdec) { + return 0; /* FIXME: implement */ } @@ -460,6 +471,42 @@ current_time_sub_ntptime(sender_info->last_ctl_ntptime); +static void +init_rtcp_bye(struct rtcp_bye* rtcp_bye, guint32 myid) +{ + /* FIXME: implement */ +} +send_rtcp(const GstRtpdec* rtpdec, const char* buffer, guint32 bufsize) +static guint +size_recv_report(guint num_recp_block) + /* FIXME implement */ +static guint +size_sdes_cname(GString* cname) +static void +init_rtcp_cname(struct rtcp_sdes* sdes, guint32 myid, GString* cname) static guint32 middle_bits(const struct ntptime time) return (time.integer << 16) + (time.frac >> 16); |
From: <ra...@fr...> - 2004-08-19 23:10:04
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Thu Aug 19 2004 16:10:02 PDT Log message: rtp_report.c: correct some comments Modified files: rtpdec : rtp_report.c Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_report.c.diff?r1=1.13&r2=1.14 ====Begin Diffs==== Index: rtp_report.c =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_report.c,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- rtp_report.c 19 Aug 2004 23:09:08 -0000 1.13 +++ rtp_report.c 19 Aug 2004 23:09:50 -0000 1.14 @@ -17,8 +17,7 @@ #include "rtp_packet.h" /* Todo list in this file: - implement get_interval_for_bye - implement decide_num_recp_blocks + implement empty functions take care of races. The main thread removing a sender from the list, while we are building the RTCP message with the list of senders. */ |
From: <ra...@fr...> - 2004-08-20 21:37:29
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Fri Aug 20 2004 14:37:28 PDT Log message: rtp_packet.c Implemented missing functions (warning: it does not compile) Modified files: rtpdec : gstrtpdec.c rtp_report.c todo Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c.diff?r1=1.11&r2=1.12 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_report.c.diff?r1=1.14&r2=1.15 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/todo.diff?r1=1.3&r2=1.4 ====Begin Diffs==== Index: gstrtpdec.c =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- gstrtpdec.c 9 Apr 2004 14:00:33 -0000 1.11 +++ gstrtpdec.c 20 Aug 2004 21:37:15 -0000 1.12 @@ -1,7 +1,7 @@ /* Copyright (c) 2003 Ramon Garcia Fernandez - Sponsored by CSOA Laboratorio 3 http://laboratorio3.net Based on the template code copyright (C) 1999 Erik Walthinsen <om...@cs...> + With the support of the GStream developement team. */ #include <gst/gst.h> @@ -26,7 +26,6 @@ "Rtp decoder", "0.0", "Ramon Garcia Fernandez. " - "Sponsored by CSOA Laboratorio 3 http://laboratorio3.net", "(C) 2002, 2003" }; Index: rtp_report.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_report.c,v retrieving revision 1.14 retrieving revision 1.15 diff -u -d -r1.14 -r1.15 --- rtp_report.c 19 Aug 2004 23:09:50 -0000 1.14 +++ rtp_report.c 20 Aug 2004 21:37:15 -0000 1.15 @@ -17,7 +17,6 @@ #include "rtp_packet.h" /* Todo list in this file: - implement empty functions take care of races. The main thread removing a sender from the list, while we are building the RTCP message with the list of senders. */ @@ -68,9 +67,9 @@ static guint size_recv_report(guint num_recp_blocks); -static guint size_sdes_cname(GString* cname); +static guint size_sdes_cname(const GString* cname); -static void init_rtcp_cname(struct rtcp_sdes* sdes, guint32 myid, GString* cname); +static void init_rtcp_cname(const GstRtpdec* rtpdec, struct rtcp_sdes* sdes, guint32 myid, const GString* cname); static void fill_reception_block (struct reception_block *reception_block, const struct sender_info *sender_info); @@ -300,7 +299,7 @@ if (!buffer) { return; } - recv = (struct rtcp_recv_report *) recv; + recv = (struct rtcp_recv_report *) buffer; sdes_cname = (struct rtcp_sdes *) (recv + sizeof (struct rtcp_recv_report)); store_stats_in_rr (rtpdec, recv, num_recp_blocks); init_rtcp_cname (sdes_cname, rtpdec->myid, rtpdec->cname); @@ -397,11 +396,28 @@ } + +/* Evaluate how many reception records fit in a packet, taking into account the MTU */ static guint -decide_num_recp_blocks(const GstRtpdec * rtpdec) +decide_num_recp_blocks(const GstRtpdec * rtpdec, const GString* cname, gboolean do_bye) { - return 0; - /* FIXME: implement */ + guint base_size, factor, max_recp_blocks, num_recp_blocks; + guint factor31, num_31_blocks, num_reminder_recp; + base_size = sizeof(struct rtcp_recv_report) - sizeof(struct reception_block) + + size_sdes_cname(cname); + if (do_bye) { + base_size += sizeof(struct rtcp_bye); + } + factor = sizeof(struct reception_block); + factor31 = 31*factor + sizeof(rtcp_recv_report) - sizeof(struct reception_block); + num_31_blocks = (rtpdec->mtu - base_size)/factor31; + num_reminder_recp = (rtpdec->mtu - base_size - factor31*num31_blocks)/factor; + max_recp_blocks = num_reminder_recp + 31*num_31_blocks; + num_recp_blocks = g_hash_table_size(rtpdec->sender_list); + if (num_recp_blocks > max_recp_blocks) { + num_recp_blocks = max_recp_blocks; + return num_recp_blocks; /* Store statistics in a RTCP receiver record */ @@ -474,13 +490,14 @@ static void init_rtcp_bye(struct rtcp_bye* rtcp_bye, guint32 myid) + init_rtcp_common(rtcp_bye->common, BYE, sizeof(struct rtcp_bye), 1); + rtcp_bye->identifier[0] = myid; send_rtcp(const GstRtpdec* rtpdec, const char* buffer, guint32 bufsize) + gst_addr_try_send(rtpdec->control_socket, remote_address, remote_control_port, buffer, bufsize); @@ -488,21 +505,35 @@ size_recv_report(guint num_recp_block) - /* FIXME implement */ + guint size_block_31; + guint size_single_recp; + size_single_recp = sizeof(struct reception_block); + size_block_31 = sizeof(struct rtp_recv_report) + 30*sizeof(struct reception_block); + return (num_recp_block/31)*size_block_31 + (num_recp_block % 31)*size_single_recp; static guint -size_sdes_cname(GString* cname) +size_sdes_cname(const GString* cname) + gunit cname_item_size, chunk_size; + cname_item_size = sizeof(struct sdes_item) - 1 + cname->len; + chunk_size = sizeof(struct sdes_chunk) - sizeof(struct sdes_item) + cname_item_size; + chunk_size = ((chunk_size + 7)/8)*8; /* round up to next multiple of 8 */ + return sizeof(struct rtcp_sdes) - sizeof(struct sdes_chunk) + chunk_size; static void -init_rtcp_cname(struct rtcp_sdes* sdes, guint32 myid, GString* cname) +init_rtcp_cname(const GstRtpdec* rtpdec, struct rtcp_sdes* sdes, guint32 myid, const GString* cname) + struct sdes_chunk* chunk; + struct sdes_item* item; + init_rtcp_common(sdes->common, SDES, size_sdes_cname(cname), 1); + chunk = &sdes->chunks[0]; + chunk->identifier = myid; + item = &chunk->items[0]; + item->type = CNAME; + item->length = cname->len; + memcpy(item->text, cname->str, cname->len); Index: todo RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/todo,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- todo 13 Aug 2004 10:30:53 -0000 1.3 +++ todo 20 Aug 2004 21:37:15 -0000 1.4 @@ -1,6 +1,5 @@ * Short term -Finish rtp_report.c: send_report. Update rtpdec.c, so that it sends a message when a new receiver is got or dropped. Remember, now we have new_num_members in GstRtpdec, that must be used for this purpose. Implement gclist.c and actually update GCLists. @@ -25,4 +24,4 @@ Warning: added identifier field to sender_info. Think about races. While the reporting thread is preparing the report, -the other thread removes an entry because of a BYE message. \ No newline at end of file +the other thread removes an entry because of a BYE message. |
From: <ra...@fr...> - 2004-08-21 12:00:22
|
CVS Root: /cvs/gstreamer Module: gst-sandbox Changes by: ramon Date: Sat Aug 21 2004 05:00:19 PDT Log message: compilation fixes Modified files: rtpdec : Makefile address.c address.h gstrtpdec.c rtp_report.c rtpdec.c rtpdec.h socket_fns.c Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/Makefile.diff?r1=1.5&r2=1.6 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/address.c.diff?r1=1.4&r2=1.5 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/address.h.diff?r1=1.9&r2=1.10 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c.diff?r1=1.12&r2=1.13 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtp_report.c.diff?r1=1.15&r2=1.16 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtpdec.c.diff?r1=1.7&r2=1.8 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/rtpdec.h.diff?r1=1.7&r2=1.8 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-sandbox/rtpdec/socket_fns.c.diff?r1=1.9&r2=1.10 ====Begin Diffs==== Index: Makefile =================================================================== RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/Makefile,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- Makefile 19 Aug 2004 22:52:51 -0000 1.5 +++ Makefile 21 Aug 2004 12:00:06 -0000 1.6 @@ -1,4 +1,4 @@ -CFLAGS=$(shell pkg-config --cflags gstreamer-0.8) -DGST_PACKAGE='"GStreamer"' -DGST_ORIGIN='"http://gstreamer.net"' -DVERSION='"0.0"' -Wall -Werror +CFLAGS=$(shell pkg-config --cflags gstreamer-0.8) -DGST_PACKAGE='"GStreamer"' -DGST_ORIGIN='"http://gstreamer.net"' -DVERSION='"0.0"' -DHAVE_USER_MTU -Wall -Werror check: gstrtpdec.o rtpdec.o rtp_report.o socket_fns.o Index: address.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/address.c,v retrieving revision 1.4 diff -u -d -r1.4 -r1.5 --- address.c 20 Mar 2004 23:33:28 -0000 1.4 +++ address.c 21 Aug 2004 12:00:07 -0000 1.5 @@ -171,7 +171,7 @@ gboolean -gst_addr_allowed (GstAuthorizedAddrs * acls, struct sockaddr_in6 *peer) +gst_addr_allowed (const GstAuthorizedAddrs * acls, struct sockaddr_in6 *peer) { GstAuthorizedAddr *acl_entry; GstNumAddr *addr; Index: address.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/address.h,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- address.h 9 Apr 2004 00:57:47 -0000 1.9 +++ address.h 21 Aug 2004 12:00:07 -0000 1.10 @@ -66,9 +66,10 @@ gboolean gst_addr_try_connect (int socket, const GstNumAddress * address, in_port_t port); -void gst_addr_try_send (int socket, GstNumAddress * remote, in_port_t port, +void gst_addr_try_send (int socket, const GstNumAddress * remote, in_port_t port, const char *data, guint size); +gboolean gst_addr_allowed (const GstAuthorizedAddrs * acls, struct sockaddr_in6 *peer); void gst_addr_delete_address (GstAddress * addr); Index: gstrtpdec.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/gstrtpdec.c,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- gstrtpdec.c 20 Aug 2004 21:37:15 -0000 1.12 +++ gstrtpdec.c 21 Aug 2004 12:00:07 -0000 1.13 @@ -13,21 +13,19 @@ #include <sys/poll.h> #include <stdlib.h> #include <assert.h> +#include <unistd.h> #include "gstrtpdec.h" #include "socket_fns.h" #include "rtpdec.h" #include "rtp_report.h" -static GstElementDetails rtpdec_details = { +static GstElementDetails rtpdec_details = +GST_ELEMENT_DETAILS( "Rtpdec", "Source/Rtpdec", - "LGPL", "Rtp decoder", - "0.0", - "Ramon Garcia Fernandez. " - "(C) 2002, 2003" -}; + "Ramon Garcia Fernandez. "); /* Filter signals and args */ @@ -59,14 +57,21 @@ GST_PAD_SOMETIMES, GST_STATIC_CAPS_ANY); +static void gst_rtpdec_base_init (gpointer g_class); + static void gst_rtpdec_class_init (GstRtpdecClass * klass); static void gst_rtpdec_init (GstRtpdec * filter); +static void gst_rtpdec_finalize (GObject * element); static void gst_rtpdec_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_rtpdec_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); +/* This element is loop based because when it starts there is no pad, + thus making it imposible to be get based */ static void gst_rtpdec_main_loop (GstElement * element); static void gst_rtpdec_set_clock (GstElement * element, GstClock * clock); @@ -90,7 +95,7 @@ static const GTypeInfo rtpdec_info = { sizeof (GstRtpdecClass), NULL, - NULL, + (GBaseInitFunc) gst_rtpdec_base_init, (GClassInitFunc) gst_rtpdec_class_init, @@ -104,6 +109,13 @@ return rtpdec_type; } +static void +gst_rtpdec_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + gst_element_class_set_details (element_class, &rtpdec_details); +} /* initialize the rtpdec's class */ static void @@ -118,6 +130,7 @@ gst_rtpdec_class = (GstRtpdecClass *) klass; + gobject_class->finalize = gst_rtpdec_finalize; gobject_class->set_property = gst_rtpdec_set_property; gobject_class->get_property = gst_rtpdec_get_property; @@ -135,7 +148,6 @@ gst_rtpdec_init (GstRtpdec * rtpdec) - GError *error; GstElement *element; element = GST_ELEMENT (rtpdec); @@ -182,8 +194,10 @@ -gst_rtpdec_finalize (GstRtpdec * element) +gst_rtpdec_finalize (GObject * object) + GstRtpdec * element = GST_RTPDEC(object); + g_assert(element != NULL); if (element->mapping) { gst_rtpdec_delete_mapping (element->mapping); } @@ -249,12 +263,12 @@ case ARG_LOCAL_ADDR: addr = (GstAddress *) g_value_get_boxed (value); gst_rtpdec_set_local_addr (rtpdec, addr); - gst_address_free (addr); + g_boxed_free (GST_TYPE_ADDRESS, addr); break; case ARG_REMOTE_HOST: gst_rtpdec_set_remote_addr (rtpdec, addr); case ARG_REMOTE_DATA_PORT: port_val = g_value_get_int (value); @@ -267,7 +281,7 @@ case ARG_MULTICAST_ADDR: gst_rtpdec_set_multicast_addr (rtpdec, addr); case ARG_MEDIA_MIME_MAPPING: mapping = (GHashTable *) g_value_get_boxed (value); @@ -275,7 +289,7 @@ case ARG_BANDWIDTH: bandwidth = g_value_get_int (value); - gst_rtpdec_set_bandwith (rtpdec, value); + gst_rtpdec_set_bandwidth (rtpdec, bandwidth); default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -327,6 +341,7 @@ return sucess ? GST_STATE_SUCCESS : GST_STATE_FAILURE; } else if (current_state == GST_STATE_READY && next_state == GST_STATE_PAUSED) { gst_rtpdec_connect (rtpdec); + return GST_STATE_SUCCESS; } else if (current_state == GST_STATE_PAUSED && next_state == GST_STATE_PLAYING) { return GST_STATE_SUCCESS; Index: rtp_report.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtp_report.c,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- rtp_report.c 20 Aug 2004 21:37:15 -0000 1.15 +++ rtp_report.c 21 Aug 2004 12:00:07 -0000 1.16 @@ -11,6 +11,7 @@ #include <glib/gmain.h> #include <unistd.h> +#include <string.h> @@ -54,7 +55,7 @@ static void get_interval_for_bye (const GstRtpdec * rtpdec, GTimeVal * result); -static guint decide_num_recp_blocks (const GstRtpdec * rtpdec); +static guint decide_num_recp_blocks (const GstRtpdec * rtpdec, const GString* cname, gboolean do_bye); static void init_rtcp_common (struct rtcp_common_header *rtcp, rtcp_packet_type packet_type, guint16 length, guint num_sources); @@ -69,7 +70,7 @@ static guint size_sdes_cname(const GString* cname); -static void init_rtcp_cname(const GstRtpdec* rtpdec, struct rtcp_sdes* sdes, guint32 myid, const GString* cname); +static void init_rtcp_cname(struct rtcp_sdes* sdes, guint32 myid, const GString* cname); static void fill_reception_block (struct reception_block *reception_block, const struct sender_info *sender_info); @@ -288,7 +289,7 @@ guint sdes_size, recv_report_size; guint num_recp_blocks; - num_recp_blocks = decide_num_recp_blocks (rtpdec); + num_recp_blocks = decide_num_recp_blocks (rtpdec, rtpdec->cname, do_bye); recv_report_size = size_recv_report (num_recp_blocks); sdes_size = size_sdes_cname (rtpdec->cname); bufsize = recv_report_size + sdes_size; @@ -409,9 +410,9 @@ base_size += sizeof(struct rtcp_bye); factor = sizeof(struct reception_block); - factor31 = 31*factor + sizeof(rtcp_recv_report) - sizeof(struct reception_block); + factor31 = 31*factor + sizeof(struct rtcp_recv_report) - sizeof(struct reception_block); num_31_blocks = (rtpdec->mtu - base_size)/factor31; - num_reminder_recp = (rtpdec->mtu - base_size - factor31*num31_blocks)/factor; + num_reminder_recp = (rtpdec->mtu - base_size - factor31*num_31_blocks)/factor; max_recp_blocks = num_reminder_recp + 31*num_31_blocks; num_recp_blocks = g_hash_table_size(rtpdec->sender_list); if (num_recp_blocks > max_recp_blocks) { @@ -490,14 +491,15 @@ static void init_rtcp_bye(struct rtcp_bye* rtcp_bye, guint32 myid) - init_rtcp_common(rtcp_bye->common, BYE, sizeof(struct rtcp_bye), 1); + init_rtcp_common(&rtcp_bye->common, BYE, sizeof(struct rtcp_bye), 1); rtcp_bye->identifier[0] = myid; send_rtcp(const GstRtpdec* rtpdec, const char* buffer, guint32 bufsize) - gst_addr_try_send(rtpdec->control_socket, remote_address, remote_control_port, buffer, bufsize); + gst_addr_try_send(rtpdec->control_socket, & rtpdec->remote_address, rtpdec->remote_control_port, + buffer, bufsize); @@ -508,14 +510,14 @@ guint size_block_31; guint size_single_recp; size_single_recp = sizeof(struct reception_block); - size_block_31 = sizeof(struct rtp_recv_report) + 30*sizeof(struct reception_block); + size_block_31 = sizeof(struct rtcp_recv_report) + 30*sizeof(struct reception_block); return (num_recp_block/31)*size_block_31 + (num_recp_block % 31)*size_single_recp; static guint size_sdes_cname(const GString* cname) - gunit cname_item_size, chunk_size; + guint cname_item_size, chunk_size; cname_item_size = sizeof(struct sdes_item) - 1 + cname->len; chunk_size = sizeof(struct sdes_chunk) - sizeof(struct sdes_item) + cname_item_size; chunk_size = ((chunk_size + 7)/8)*8; /* round up to next multiple of 8 */ @@ -523,11 +525,11 @@ -init_rtcp_cname(const GstRtpdec* rtpdec, struct rtcp_sdes* sdes, guint32 myid, const GString* cname) +init_rtcp_cname(struct rtcp_sdes* sdes, guint32 myid, const GString* cname) struct sdes_chunk* chunk; struct sdes_item* item; - init_rtcp_common(sdes->common, SDES, size_sdes_cname(cname), 1); + init_rtcp_common(&sdes->common, SOURCE_DESCRIPTION, size_sdes_cname(cname), 1); chunk = &sdes->chunks[0]; chunk->identifier = myid; item = &chunk->items[0]; Index: rtpdec.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtpdec.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- rtpdec.c 9 Aug 2004 19:07:37 -0000 1.7 +++ rtpdec.c 21 Aug 2004 12:00:07 -0000 1.8 @@ -1,5 +1,7 @@ #include <pwd.h> static void gst_rtpdec_handle_control_packet (GstRtpdec * element, char *data, @@ -453,7 +455,7 @@ return; } - assert (sender_info->handler != NULL); + g_assert (sender_info->handler != NULL); runtime_sample_rate = gst_irtpdec_handler_get_sample_rate (sender_info->handler, data, @@ -585,7 +587,7 @@ (gpointer) result); } else { - assert (result->magic == sender_magic); + g_assert (result->magic == sender_magic); return result; @@ -639,7 +641,7 @@ result->name = NULL; result->email = NULL; - assert (result->magic == recv_magic); + g_assert (result->magic == recv_magic); @@ -659,7 +661,7 @@ stored_identifier = (guint32 *) stored_identifier_gptr; result = (struct recv_info *) result_gptr; if (found) { - assert (result != NULL); + g_assert (result != NULL); if (result->cname != NULL) { g_string_free (result->cname, TRUE); @@ -704,6 +706,35 @@ +void +gst_rtpdec_set_mapping (GstRtpdec * rtpdec, GHashTable * mapping) + /* FIXME: implement */ +gst_rtpdec_set_bandwidth (GstRtpdec *rtpdec, guint bandwidth) +gst_rtpdec_delete_mapping (GHashTable * mapping) +void gst_rtpdec_delete_sender_list (GHashTable * sender_list) +void gst_rtpdec_delete_recv_list (GHashTable * recv_list) guint32 create_id () @@ -748,11 +779,11 @@ void gst_rtpdec_connect (GstRtpdec * element) - gst_rtpdec_disconnect (GstRtpdec * element) Index: rtpdec.h RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/rtpdec.h,v --- rtpdec.h 20 Mar 2004 23:33:28 -0000 1.7 +++ rtpdec.h 21 Aug 2004 12:00:07 -0000 1.8 @@ -13,11 +13,13 @@ void gst_rtpdec_set_mapping (GstRtpdec * rtpdec, GHashTable * mapping); +void gst_rtpdec_set_bandwidth (GstRtpdec * rtpdec, guint bandwidth); void gst_rtpdec_disconnect (GstRtpdec * rtpdec); void gst_rtpdec_connect (GstRtpdec * rtpdec); -guint32 createid (void); +guint32 create_id (void); GString *make_cname (void); Index: socket_fns.c RCS file: /cvs/gstreamer/gst-sandbox/rtpdec/socket_fns.c,v --- socket_fns.c 9 Apr 2004 14:00:33 -0000 1.9 +++ socket_fns.c 21 Aug 2004 12:00:07 -0000 1.10 @@ -2,6 +2,7 @@ wait for incoming data, and check if a packet is authorized */ #include <sys/ioctl.h> #include <sys/socket.h> @@ -100,6 +101,7 @@ #endif } while (try_again); + return TRUE; #ifdef HAVE_USER_PMTU @@ -159,14 +161,13 @@ return gst_addr_in_list (&element->remote_address, &addr->sin6_addr); - return gst_addr_allowed (element->authorized_senders, addr); + return gst_addr_allowed (&element->authorized_senders, addr); gst_rtpdec_open_conn (GstRtpdec * element) - int error; gboolean bound; bound = FALSE; @@ -243,8 +244,6 @@ static gboolean try_bind (GstRtpdec * element, in_port_t port, int *socket_fd) - struct sockaddr_in6 addr; - int i; gboolean result; *socket_fd = socket (AF_INET6, SOCK_DGRAM, 0); @@ -260,11 +259,7 @@ try_bind_random (GstRtpdec * element, int *socket) - gboolean result; - result = gst_addr_try_bind (*socket, &element->local_address, 0); + return gst_addr_try_bind (*socket, &element->local_address, 0); |