X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=ortp_send.c;h=17f14d17618e6b4893a176838b16ec9c8880437d;hp=46b3ece763aaed16f8de964a40d5c5c91d10eaf2;hb=d27b31524e1d60ad4fdbeb606bba31ba0ee54048;hpb=db34194eaab9819772bd55ea1ab08c719ed8f1c8;ds=sidebyside diff --git a/ortp_send.c b/ortp_send.c index 46b3ece7..17f14d17 100644 --- a/ortp_send.c +++ b/ortp_send.c @@ -1,61 +1,52 @@ /* - * Copyright (C) 2005-2006 Andre Noll + * Copyright (C) 2005-2008 Andre Noll * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + * Licensed under the GPL v2. For licencing details see COPYING. */ /** \file ortp_send.c para_server's ortp sender */ #include +#include #include "server.cmdline.h" -#include "server.h" +#include "para.h" +#include "error.h" +#include "string.h" +#include "afh.h" #include "afs.h" -#include "send.h" +#include "server.h" +#include "vss.h" #include "list.h" +#include "send.h" #include "ortp.h" -#include "string.h" -/** \cond convert in_addr to ascii */ +/** Convert in_addr to ascii. */ #define TARGET_ADDR(oc) inet_ntoa((oc)->addr) -/** \endcond */ -extern struct gengetopt_args_info conf; - -/** describes one entry in the list of targets for the ortp sender */ +/** Describes one entry in the list of targets for the ortp sender. */ struct ortp_target { -/** address info */ + /** Address info. */ struct in_addr addr; -/** whether the ortp sender is activated */ + /** Whether the ortp sender is activated. */ int status; -/** the ortp timestamp increases by this amount */ - int chunk_ts; -/** the currently used timestamp for this target */ - int last_ts; -/** the position of this target in the list of targets */ + /** The ortp timestamp increases by this amount. */ + uint32_t chunk_ts; + /** The currently used timestamp for this target. */ + uint32_t last_ts; + /** The position of this target in the list of targets. */ struct list_head node; -/** the UDP port */ + /** The UDP port. */ int port; -/** non-zero if at least one chunk has been sent to this target */ + /** Non-zero if at least one chunk has been sent to this target. */ int streaming; -/** the session pointer from libortp */ + /** The session pointer from libortp. */ RtpSession *session; }; static struct list_head targets; static struct sender *self; +static int sender_status; static void ortp_delete_target(struct ortp_target *ot, const char *msg) { @@ -69,26 +60,43 @@ static void ortp_delete_target(struct ortp_target *ot, const char *msg) free(ot); } -static void ortp_send_buf(char *buf, int len, long unsigned chunks_sent) +static void ortp_send_buf(char *buf, size_t len, long unsigned chunks_sent) { struct ortp_target *ot, *tmp; - int ret; + int ret, ortp_len = len; /* rtp_session_send_with_ts expects int */ + if (ortp_len < 0) + return; list_for_each_entry_safe(ot, tmp, &targets, node) { - int ts; + uint32_t ts; if (!ot->session) continue; WRITE_CHUNK_TS(buf, ot->chunk_ts); ts = ot->chunk_ts * chunks_sent; - ret = rtp_session_send_with_ts(ot->session, buf, len, ts); + ret = rtp_session_send_with_ts(ot->session, + (unsigned char*)buf, ortp_len, ts); ot->last_ts = ts; if (ret < 0) ortp_delete_target(ot, "send error"); - if (ret != len +12) + if (ret != len + 12) PARA_NOTICE_LOG("short write %d\n", ret); } } +static int set_multicast(RtpSession *s) +{ + unsigned char loop = 1; + int ret; + + ret = setsockopt(s->rtp.socket, + IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)); + if (ret < 0) { + PARA_ERROR_LOG("IP_MULTICAST_LOOP error %d\n", ret); + + } + return 1; +} + static void ortp_init_session(struct ortp_target *ot) { RtpSession *s; @@ -110,13 +118,15 @@ static void ortp_init_session(struct ortp_target *ot) if (ret < 0) { rtp_session_destroy(ot->session); ot->session = NULL; + return; } + set_multicast(s); } -/* called by afs */ +/* called by vss */ static void ortp_shutdown_targets(void) { - char buf[ORTP_AUDIO_HEADER_LEN]; + unsigned char buf[ORTP_AUDIO_HEADER_LEN]; struct ortp_target *ot, *tmp; WRITE_PACKET_TYPE(buf, ORTP_EOF); @@ -133,26 +143,37 @@ static void ortp_shutdown_targets(void) } } -static int need_extra_header(struct audio_format_handler *af, - long unsigned chunks_sent) +static int need_extra_header(long unsigned current_chunk) { - /* FIXME: No need to compute this on every run */ - int mod = conf.ortp_header_interval_arg / (tv2ms(&af->chunk_tv) + 1); - if (mod && (chunks_sent % mod)) + static struct timeval last_header; + struct timeval now, diff; + + if (!current_chunk) return 0; + gettimeofday(&now, NULL); + tv_diff(&now, &last_header, &diff); + if (tv2ms(&diff) < conf.ortp_header_interval_arg) + return 0; + last_header = now; return 1; } -static void ortp_send(struct audio_format_handler *af, long unsigned current_chunk, - long unsigned chunks_sent, const char *buf, size_t len) +static void ortp_send(long unsigned current_chunk, long unsigned chunks_sent, + const char *buf, size_t len, const char *header_buf, + size_t header_len) { struct ortp_target *ot, *tmp; size_t sendbuf_len; - int header_len = 0; - int packet_type = ORTP_DATA, stream_type = af && af->get_header_info; /* header stream? */ - char *sendbuf, *header_buf = NULL; + int packet_type = ORTP_DATA; + char *sendbuf; + struct timeval *chunk_tv; + + if (sender_status != SENDER_ON) + return; - if (self->status != SENDER_ON) +// PARA_NOTICE_LOG("sending %lu\n", current_chunk); + chunk_tv = vss_chunk_time(); + if (!chunk_tv) return; list_for_each_entry_safe(ot, tmp, &targets, node) { if (!ot->session) { @@ -162,18 +183,15 @@ static void ortp_send(struct audio_format_handler *af, long unsigned current_chu } if (!ot->chunk_ts) ot->chunk_ts = rtp_session_time_to_ts(ot->session, - tv2ms(&af->chunk_tv)); + (int)tv2ms(chunk_tv)); // PARA_DEBUG_LOG("len: %d, ts: %lu, ts: %d\n", // len, ot->chunk_ts * chunks_sent, ot->chunk_ts); ot->streaming = 1; } if (list_empty(&targets)) return; - if (stream_type) { - header_buf = af->get_header_info(&header_len); - if (!need_extra_header(af, chunks_sent)) - header_len = 0; - } + if (!need_extra_header(current_chunk)) + header_len = 0; sendbuf_len = ORTP_AUDIO_HEADER_LEN + header_len + len; sendbuf = para_malloc(sendbuf_len); if (!current_chunk) @@ -181,8 +199,8 @@ static void ortp_send(struct audio_format_handler *af, long unsigned current_chu else if (header_len) packet_type = ORTP_HEADER; WRITE_PACKET_TYPE(sendbuf, packet_type); - WRITE_CHUNK_TIME(sendbuf, af->chunk_tv.tv_usec); - WRITE_STREAM_TYPE(sendbuf, stream_type); + WRITE_CHUNK_TIME(sendbuf, chunk_tv->tv_usec); + WRITE_STREAM_TYPE(sendbuf, header_buf? 1 : 0); WRITE_HEADER_LEN(sendbuf, header_len); if (header_len) memcpy(sendbuf + ORTP_AUDIO_HEADER_LEN, header_buf, @@ -195,14 +213,14 @@ static void ortp_send(struct audio_format_handler *af, long unsigned current_chu static int ortp_com_on(__a_unused struct sender_command_data *scd) { - self->status = SENDER_ON; + sender_status = SENDER_ON; return 1; } static int ortp_com_off(__a_unused struct sender_command_data *scd) { ortp_shutdown_targets(); - self->status = SENDER_OFF; + sender_status = SENDER_OFF; return 1; } @@ -227,7 +245,7 @@ static void ortp_add_target(int port, struct in_addr *addr) ot->addr = *addr; PARA_INFO_LOG("adding to target list (%s:%d)\n", TARGET_ADDR(ot), ot->port); - list_add(&ot->node, &targets); + para_list_add(&ot->node, &targets); } static int ortp_com_add(struct sender_command_data *scd) @@ -249,10 +267,11 @@ static char *ortp_info(void) tgts = tmp; } ret = make_message( - "ortp status: %s\n" - "ortp default port: udp %d\n" - "ortp targets: %s\n", - (self->status == SENDER_ON)? "on" : "off", + "ortp sender:\n" + "\tstatus: %s\n" + "\tport: udp %d\n" + "\ttargets: %s\n", + (sender_status == SENDER_ON)? "on" : "off", conf.ortp_default_port_arg, tgts? tgts : "(none)" ); @@ -274,7 +293,7 @@ static void ortp_init_target_list(void) if (!p) goto err; *p = '\0'; - if (!inet_aton(arg, &addr)) + if (!inet_pton(AF_INET, arg, &addr)) goto err; port = atoi(++p); if (port < 0 || port > 65535) @@ -290,13 +309,6 @@ success: } } -static void ortp_pre_select(__a_unused struct audio_format_handler *af, - __a_unused int *max_fileno, __a_unused fd_set *rfds, - __a_unused fd_set *wfds) -{ - return; -} - static char *ortp_help(void) { return make_message( @@ -320,7 +332,7 @@ void ortp_send_init(struct sender *s) s->info = ortp_info; s->help = ortp_help; s->send = ortp_send; - s->pre_select = ortp_pre_select; + s->pre_select = NULL; s->post_select = NULL; s->shutdown_clients = ortp_shutdown_targets; s->client_cmds[SENDER_ON] = ortp_com_on; @@ -330,9 +342,9 @@ void ortp_send_init(struct sender *s) s->client_cmds[SENDER_ADD] = ortp_com_add; s->client_cmds[SENDER_DELETE] = ortp_com_delete; self = s; - s->status = SENDER_OFF; + sender_status = SENDER_OFF; ortp_init_target_list(); if (!conf.ortp_no_autostart_given) - s->status = SENDER_ON; - PARA_DEBUG_LOG("%s", "ortp sender init complete\n"); + sender_status = SENDER_ON; + PARA_DEBUG_LOG("ortp sender init complete\n"); }