1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
|
/*
* rtpdemo: A simple rtp application that sends and receives data.
*
* (C) 2000-2001 University College London.
*/
#include <sys/time.h>
#include <ctype.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "uclconf.h"
#include "config_unix.h"
#include "config_win32.h"
#include "debug.h"
#include "memory.h"
#include "rtp.h"
static void
usage()
{
printf("Usage: rtpdemo [switches] address port\n");
printf("Valid switches are:\n");
printf(" -f\t\tFilter local packets out of receive stream.\n");
printf(" -l\t\tListen and do not transmit data.\n");
exit(-1);
}
/* ------------------------------------------------------------------------- */
/* RTP callback related */
static void
sdes_print(struct rtp *session, uint32_t ssrc, rtcp_sdes_type stype) {
const char *sdes_type_names[] = {
"end", "cname", "name", "email", "telephone",
"location", "tool", "note", "priv"
};
const uint8_t n = sizeof(sdes_type_names) / sizeof(sdes_type_names[0]);
if (stype > n) {
/* Theoretically impossible */
printf("boo! invalud sdes field %d\n", stype);
return;
}
printf("SSRC 0x%08x reported SDES type %s - ", ssrc,
sdes_type_names[stype]);
if (stype == RTCP_SDES_PRIV) {
/* Requires extra-handling, not important for example */
printf("don't know how to display.\n");
} else {
printf("%s\n", rtp_get_sdes(session, ssrc, stype));
}
}
static void
packet_print(struct rtp *session, rtp_packet *p)
{
printf("Received data (payload %d timestamp %06d size %d) ", p->pt, p->ts, p->data_len);
if (p->ssrc == rtp_my_ssrc(session)) {
/* Unless filtering is enabled we are likely to see
out packets if sending to a multicast group. */
printf("that I just sent.\n");
} else {
printf("from SSRC 0x%08x\n", p->ssrc);
}
}
static void
rtp_event_handler(struct rtp *session, rtp_event *e)
{
rtp_packet *p;
rtcp_sdes_item *r;
switch(e->type) {
case RX_RTP:
p = (rtp_packet*)e->data;
packet_print(session, p);
xfree(p); /* xfree() is mandatory to release RTP packet data */
break;
case RX_SDES:
r = (rtcp_sdes_item*)e->data;
sdes_print(session, e->ssrc, r->type);
break;
case RX_BYE:
break;
case SOURCE_CREATED:
printf("New source created, SSRC = 0x%08x\n", e->ssrc);
break;
case SOURCE_DELETED:
printf("Source deleted, SSRC = 0x%08x\n", e->ssrc);
break;
case RX_SR:
case RX_RR:
case RX_RR_EMPTY:
case RX_RTCP_START:
case RX_RTCP_FINISH:
case RR_TIMEOUT:
case RX_APP:
break;
}
fflush(stdout);
}
/* ------------------------------------------------------------------------- */
/* Send and receive loop. Sender use 20ms audio mulaw packets */
#define MULAW_BYTES 4 * 160
#define MULAW_PAYLOAD 0
#define MULAW_MS 4 * 20
#define MAX_ROUNDS 100
static void
rxtx_loop(struct rtp* session, int send_enable)
{
struct timeval timeout;
uint32_t rtp_ts, round;
uint8_t mulaw_buffer[MULAW_BYTES];
if (send_enable) {
printf("Sending and listening to ");
} else {
printf("Listening to ");
}
printf("%s port %d (local SSRC = 0x%08x)\n",
rtp_get_addr(session),
rtp_get_rx_port(session),
rtp_my_ssrc(session));
round = 0;
for(round = 0; round < MAX_ROUNDS; round++) {
rtp_ts = round * MULAW_MS;
/* Send control packets */
rtp_send_ctrl(session, rtp_ts, NULL);
/* Send data packets */
if (send_enable) {
rtp_send_data(session, rtp_ts, MULAW_PAYLOAD,
0, 0, 0,
(char*)mulaw_buffer, MULAW_BYTES,
0, 0, 0);
}
/* Receive control and data packets */
timeout.tv_sec = 0;
timeout.tv_usec = 0;
rtp_recv(session, &timeout, rtp_ts);
/* State maintenance */
rtp_update(session);
usleep(MULAW_MS * 1000);
xmemchk();
}
}
/* ------------------------------------------------------------------------- */
/* Main loop: parses command line and initializes RTP session */
int
main(int argc, const char *argv[])
{
const char *address = NULL;
struct rtp *session = NULL;
uint16_t port = 0;
int32_t ac, filter_me = 0, send_enable = 1;
ac = 1;
while (ac < argc && argv[ac][0] == '-') {
switch(tolower(argv[ac][1])) {
case 'f':
filter_me = 1;
break;
case 'l':
send_enable = 0;
break;
}
ac++;
}
if (argc - ac != 2) {
usage();
}
address = argv[ac];
port = atoi(argv[ac + 1]);
session = rtp_init(address, /* Host/Group IP address */
port, /* receive port */
port, /* transmit port */
16, /* time-to-live */
64000, /* B/W estimate */
rtp_event_handler, /* RTP event callback */
NULL); /* App. specific data */
if (session) {
const char *username = "Malcovich Malcovitch";
const char *telephone = "1-800-RTP-DEMO";
const char *toolname = "RTPdemo";
uint32_t my_ssrc = rtp_my_ssrc(session);
/* Set local participant info */
rtp_set_sdes(session, my_ssrc, RTCP_SDES_NAME,
username, strlen(username));
rtp_set_sdes(session, my_ssrc, RTCP_SDES_PHONE,
telephone, strlen(telephone));
rtp_set_sdes(session, my_ssrc, RTCP_SDES_TOOL,
toolname, strlen(toolname));
/* Filter out local packets if requested */
rtp_set_option(session, RTP_OPT_FILTER_MY_PACKETS, filter_me);
/* Run main loop */
rxtx_loop(session, send_enable);
/* Say bye-bye */
rtp_send_bye(session);
rtp_done(session);
} else {
printf("Could not initialize session for %s port %d\n",
address,
port);
}
return 0;
}
|