summaryrefslogtreecommitdiff
path: root/src/rtp.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rtp.cc')
-rw-r--r--src/rtp.cc262
1 files changed, 262 insertions, 0 deletions
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 <string.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+
+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<csrc_t> 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<csrc_t>::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;
+}