Mercurial > hg > audiostuff
diff intercom/rtp.cpp @ 2:13be24d74cd2
import intercom-0.4.1
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 09:57:52 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/intercom/rtp.cpp Fri Jun 25 09:57:52 2010 +0200 @@ -0,0 +1,199 @@ +/* rtp.cpp + * + * Copyright (C) DFS Deutsche Flugsicherung (2004, 2005). + * All Rights Reserved. + * Author: Andre Adrian + * + * subset of Real Time Protocol Version 2 (RFC3550) + * handling of extension and padding is missing + * + * Version 0.3 + */ + +#include <stdio.h> /* printf() */ +#include <stdlib.h> + +#include <sys/types.h> /* u_long */ +#include <sys/time.h> /* gettimeofday() */ +#include <unistd.h> /* get..() */ +#include <time.h> /* clock() */ +#include <sys/utsname.h> /* uname() */ +#include <netinet/in.h> +#include <assert.h> + +#include "intercomd.h" +#include "rtp.h" + +/* + * Return random unsigned 32-bit quantity. Use 'type' argument if + * you need to generate several different values in close succession. + * (partly from RFC 3550 A.6 Generating a Random 32-bit Identifier) + */ +unsigned long random32(int type) +{ + struct { + int type; + struct timeval tv; + clock_t cpu; + pid_t pid; + u_long hid; + uid_t uid; + gid_t gid; + struct utsname name; + } s; + + gettimeofday(&s.tv, 0); + uname(&s.name); + s.type = type; + s.cpu = clock(); + s.pid = getpid(); + s.hid = gethostid(); + s.uid = getuid(); + s.gid = getgid(); + /* also: system uptime */ + + unsigned long *us = (unsigned long *) &s; + + /* use xor to make a (bad) random */ + /* Note: remainder of long div of 32bit prim is better */ + unsigned long random = 0; + unsigned int i; + for (i = 0; i < sizeof(s) / sizeof(long); ++i) { + random ^= *us++; + } + return random; +} /* random32 */ + + +RTP::RTP() +{ + version = 2; + padding = 0; + extension = 0; + csrc_count = 0; + marker = 0; + payload_type = PT_PCMU; + ssrc = 0; + sequence = 0; + timestamp = 0; +} + +void RTP::init(int payload_type_, unsigned long ssrc_) +{ + version = 2; + padding = 0; + extension = 0; + csrc_count = 0; + marker = 0; + payload_type = payload_type_; + ssrc = ssrc_; + /* My interpretation of RFC3550 A.6: one seed is good enough */ + sequence = random32(payload_type_); + timestamp = sequence; +} + +void RTP::next(int frameduration) +{ + ++sequence; + timestamp += frameduration; +} + +void RTP::reset_csrc() +{ + csrc_count = 0; +} + +int RTP::add_csrc(unsigned long csrc_) +{ + return_if (csrc_count >= 15, ERROR); + csrc[csrc_count++] = csrc_; + + // printf("add_csrc = %08x\n", csrc_); + return OKAY; +} + +int RTP::find_csrc(unsigned long ssrc_) +{ + unsigned int i; + + if (0 == csrc_count) return NO; + // printf("find_csrc = %08x ", ssrc_); + for (i = 0; i < csrc_count; ++i) { + // printf("%08x ", csrc[i]); + if (csrc[i] == ssrc_) { + // printf("hit\n"); + return YES; + } + } + return NO; +} + +int RTP::check() +{ + // RFC3550 A.1 RTP Data Header Validity Checks + + // RTP version field must equal 2. + if (version != 2) + return -1; + + // The payload type must be known + switch (payload_type) { + case PT_PCMU: + case PT_GSM: + case PT_PCMA: + case PT_G729: + case PT_iLBC: + case PT_EFR: + case PT_G726: + case PT_SPX: + /* do nothing */ + break; + default: + return -1; + } + + // The X bit must be zero if the profile does not specify that the + // header extension mechanism may be used. Otherwise, the extension + // length field must be less than the total packet size minus the + // fixed header length and padding. + if (extension) + return -1; // hack! + + // The length of the packet must be consistent with CC and payload + // type (if payloads have a known length). + // equal to SR or RR. + // if (csrc_count != 0) + // return -1; // hack! + + // If the P bit is set, then the last octet of the packet must + // contain a valid octet count, in particular, less than the total + // packet length minus the header size. + if (padding) + return -1; // hack! + return 0; +} + +char *RTP_network_copy(char *to, RTP * from) +{ + unsigned long *ulfrom = (unsigned long *) from; + unsigned long *ulto = (unsigned long *) to; + int i; + for (i = 0; i < 3 + from->get_cc(); ++i) { + *ulto++ = htonl(*ulfrom++); + } + return (char *) ulto; +} + +char *RTP_host_copy(RTP * to, char *from) +{ + unsigned long *ulfrom = (unsigned long *) from; + unsigned long *ulto = (unsigned long *) to; + int i; + for (i = 0; i < 3; ++i) { + *ulto++ = ntohl(*ulfrom++); + } + for (i = 0; i < to->get_cc(); ++i) { + *ulto++ = ntohl(*ulfrom++); + } + return (char *) ulfrom; +}