From 60f60cc76e43197a0825ffac9aff0b7007a94175 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 20 Nov 2013 12:57:17 +0100 Subject: Framework API now complete in its first iteration. So far with support for raw, opus and amrwb. --- src/rtp.cc | 262 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 src/rtp.cc (limited to 'src/rtp.cc') diff --git a/src/rtp.cc b/src/rtp.cc new file mode 100644 index 0000000..28a9203 --- /dev/null +++ b/src/rtp.cc @@ -0,0 +1,262 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * rtp.cc + * + * Mon Sep 2 15:24:09 CEST 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of lrtp. + * + * lrtp is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * lrtp 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with lrtp; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "rtp.h" + +#include +#include +#include + +RTP::RTP() +{ + memset(&header, 0, sizeof(header)); + pads = 0; + + header.version = 2; + + memset(pload, 0, sizeof(pload)); + pload_size = 0; + + is_valid = false; +} + +void RTP::setPadding(unsigned char padding) +{ + if(padding == 0) { + header.p = 0; + pads = 0; + return; + } + header.p = 1; + pads = padding; +} + +unsigned char RTP::padding() const +{ + return pads; +} + +void RTP::setPayloadType(unsigned char pt) +{ + header.pt = pt; +} + +unsigned char RTP::payloadType() const +{ + return header.pt; +} + +void RTP::setMarker(bool bit) +{ + header.m = bit?1:0; +} + +bool RTP::marker() const +{ + return header.m; +} + +void RTP::setSeq(uint16_t seq) +{ + header.seq = htons(seq); +} + +uint16_t RTP::seq() const +{ + return ntohs(header.seq); +} + +void RTP::setTimestamp(uint32_t ts) +{ + header.ts = htonl(ts); +} + +uint32_t RTP::timestamp() const +{ + return ntohl(header.ts); +} + +void RTP::setSSrc(uint32_t ssrc) +{ + header.ssrc = htonl(ssrc); +} + +uint32_t RTP::SSrc() const +{ + return ntohl(header.ssrc); +} + +void RTP::addCSrc(csrc_t csrc) +{ + if(csrcs.size() == 15) { + printf("ERROR: Too many CSRCs (max 15).\n"); + return; // TODO: Report error! + } + csrcs.push_back(csrc); + header.cc = csrcs.size(); +} + +std::list RTP::getCSrcs() const +{ + return csrcs; +} + +void RTP::removeCSrc(csrc_t csrc) +{ + csrcs.remove(csrc); + header.cc = csrcs.size(); +} + +void RTP::clearCSrcs() +{ + csrcs.clear(); + header.cc = csrcs.size(); +} + +void RTP::setPayload(const char *pl, size_t size) +{ + if(size > MAX_RTP_PAYLOAD_SIZE) { + printf("ERROR: Payload is too big for RTP pakcet.\n"); + // TODO: Report error. + } + + memcpy(pload, pl, size); + pload_size = size; + + setValid(true); +} + +size_t RTP::payload(char *payload, size_t maxsize) const +{ + if(pload_size > maxsize) { + printf("ERROR: Payload is too big for the buffer.\n"); + return 0; // TODO: Report error. + } + + memcpy(payload, pload, pload_size); + return pload_size; +} + +size_t RTP::payloadSize() const +{ + return pload_size; +} + +const char *RTP::payloadData() const +{ + return pload; +} + +size_t RTP::packet(char *packet, size_t maxsize) const +{ + memset(packet, 0, maxsize); + + size_t total_packet_size = + sizeof(header) + sizeof(csrc_t) * csrcs.size() + pload_size + pads; + + if(total_packet_size > maxsize) { + printf("ERROR: Packet is too big for the buffer.\n"); + return 0; // TODO: Report error. + } + + char *p = packet; + + // Copy header fields. + memcpy(p, &header, sizeof(header)); + + p += sizeof(header); + + // Write CSrcs to packet + csrc_t *pcsrc = (csrc_t*)p; + std::list::const_iterator i = csrcs.begin(); + while(i != csrcs.end()) { + *pcsrc++ = htonl(*i); + i++; + } + + p += sizeof(csrc_t) * csrcs.size(); + + // TODO: Insert header extension here (if it exists) + + // Write payload to body. + memcpy(p, pload, pload_size); + + p += pload_size; + + if(pads) { + for(int i = 0; i < pads - 1; i++) *p++ = '\0'; + *p++ = (unsigned char)pads; + } + + return p - packet; +} + +void RTP::fromPacket(const char *packet, size_t size) +{ + rtp_header_t *hdr = (rtp_header_t *)packet; + + if(hdr->version != 2) { + printf("ERROR: Wrong RTP header version.\n"); + return; // TODO: Invalid RTP version error + } + + setMarker(hdr->m); + setPayloadType(hdr->pt); + setSeq(ntohs(hdr->seq)); + setTimestamp(ntohl(hdr->ts)); + setSSrc(ntohl(hdr->ssrc)); + + if(hdr->p) { + setPadding(*(unsigned char*)&packet[size - 1]); + } + + // TODO: Use header extension flag: hdr->x + + // Read out CSrc's: + csrc_t *pcsrc = (csrc_t*)(packet + sizeof(rtp_header_t)); + for(int i = 0; i < hdr->cc; i++) { + addCSrc(ntohl(*pcsrc)); + pcsrc++; + } + + // Read out payload + size_t plsz = size - (sizeof(rtp_header_t) + hdr->cc*sizeof(csrc_t) + pads); + char *pl = (char*)pcsrc; + setPayload(pl, plsz); + + setValid(true); +} + +bool RTP::isValid() +{ + return is_valid; +} + +void RTP::setValid(bool valid) +{ + is_valid = valid; +} -- cgit v1.2.3