summaryrefslogtreecommitdiff
path: root/src/lrtp.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lrtp.cc')
-rw-r--r--src/lrtp.cc273
1 files changed, 260 insertions, 13 deletions
diff --git a/src/lrtp.cc b/src/lrtp.cc
index 36da6f0..1f0b11d 100644
--- a/src/lrtp.cc
+++ b/src/lrtp.cc
@@ -27,20 +27,267 @@
*/
#include "lrtp.h"
-#ifdef TEST_LRTP
-//Additional dependency files
-//deps:
-//Required cflags (autoconf vars may be used)
-//cflags:
-//Required link options (autoconf vars may be used)
-//libs:
-#include "test.h"
+#include <string>
+#include <string.h>
+#include <map>
+#include <stdio.h>
-TEST_BEGIN;
+#include "rtp_profile.h"
+#include "rtp_profile_amrwb.h"
+#include "rtp_profile_opus.h"
+#include "rtp_profile_raw.h"
-// TODO: Put some testcode here (see test.h for usable macros).
-TEST_TRUE(false, "No tests yet!");
+#include "srtp.h"
-TEST_END;
+#ifdef __cplusplus
+extern "C" {
+#endif
-#endif/*TEST_LRTP*/
+typedef std::map<csrc_t, lrtp_profile_t *> profile_map_t;
+
+struct lrtp_t {
+ SRTP *srtp;
+ csrc_t ssrc;
+ unsigned short seq;
+ profile_map_t profiles;
+
+ csrc_t next_csrc; // for frame iterator (see get_next_frame)
+
+ std::list<outputframe_t *> framelist;
+};
+
+typedef struct {
+ lrtp_profile_id_t id;
+ struct lrtp_profile_t *(*create)(struct lrtp_t *lrtp, unsigned int csrc,
+ va_list ap);
+} profile_class_t;
+
+static const profile_class_t registered_profiles[] = {
+ { PROFILE_AMRWB, profile_amrwb_create },
+ { PROFILE_OPUS, profile_opus_create },
+ { PROFILE_RAW, profile_raw_create },
+ { }
+};
+
+EXPORT
+struct lrtp_t *lrtp_init(const char *key, unsigned int ssrc)
+{
+ struct lrtp_t *lrtp = new struct lrtp_t;
+
+ lrtp->srtp = new SRTP(key, ssrc);
+ lrtp->ssrc = ssrc;
+ lrtp->seq = 0;
+
+ return lrtp;
+}
+
+EXPORT
+void lrtp_close(struct lrtp_t *lrtp)
+{
+ delete lrtp->srtp;
+ delete lrtp;
+}
+
+EXPORT
+struct lrtp_profile_t *lrtp_create_profile(struct lrtp_t *lrtp,
+ lrtp_profile_id_t profile_id,
+ unsigned int csrc, ...)
+{
+ struct lrtp_profile_t *profile = NULL;
+
+ if(lrtp->profiles.find(csrc) != lrtp->profiles.end()) {
+ // TODO: CSRC already active
+ printf("ERROR: CSRC already active\n");
+ return NULL;
+ }
+
+ va_list ap;
+ va_start(ap, csrc);
+
+ const profile_class_t *p = registered_profiles;
+ while(p->create) {
+ if(p->id == profile_id) {
+ profile = p->create(lrtp, csrc, ap);
+ profile->process_finished = NULL; // TODO: Figure out a way to set non-profile specific options.
+ break;
+ }
+ p++;
+ }
+
+ va_end(ap);
+
+ if(profile) {
+ profile->id = PROFILE_RAW;
+ profile->lrtp = lrtp;
+ profile->csrc = csrc;
+
+ lrtp->profiles[csrc] = profile;
+ }
+
+ return profile;
+}
+
+EXPORT
+void lrtp_destroy_profile(struct lrtp_t *lrtp, unsigned int csrc)
+{
+ if(lrtp->profiles.find(csrc) == lrtp->profiles.end()) {
+ // TODO: CSRC not found
+ printf("ERROR: CSRC not found\n");
+ return;
+ }
+
+ struct lrtp_profile_t *profile = lrtp->profiles[csrc];
+ profile->destroy(profile);
+ lrtp->profiles.erase(csrc);
+}
+
+EXPORT
+int lrtp_enqueue_frame(struct lrtp_profile_t *profile,
+ const char *data, size_t size)
+{
+ inputframe_t *frame = new inputframe_t();
+ frame->data = data;
+ frame->size = size;
+ frame->offset = 0;
+
+ profile->framelist.push_back(frame);
+
+ return 0;
+}
+
+static lrtp_profile_t *get_next_profile(struct lrtp_t *lrtp)
+{
+ // TODO: This function /should/ return the next profile containing frame data,
+ // not just the next profile in the list (regardless of it's framequeue being
+ // empty!).
+
+ if(lrtp->profiles.size() == 0) return NULL; // No profiles
+
+ profile_map_t::iterator i = lrtp->profiles.find(lrtp->next_csrc);
+
+ if(i == lrtp->profiles.end()) {
+ i = lrtp->profiles.begin();
+ }
+
+ struct lrtp_profile_t *profile = i->second;
+
+ i++;
+
+ if(i == lrtp->profiles.end()) {
+ i = lrtp->profiles.begin();
+ }
+
+ lrtp->next_csrc = i->second->csrc;
+
+ return profile;
+}
+
+EXPORT
+int lrtp_pack(struct lrtp_t *lrtp, char *packet, size_t maxsize)
+{
+ //if(!profile) return PACK_MISSING_PROFILE;
+
+ // TODO: Check profile magic word
+
+ struct lrtp_profile_t *profile = get_next_profile(lrtp);
+
+ if(profile == NULL || profile->framelist.size() == 0) return 0;
+
+ inputframe_t *frame = profile->framelist.front();
+
+ RTP rtp;
+ rtp.setSSrc(lrtp->ssrc);
+ //rtp.setTimestamp(ts); // TODO...
+ rtp.setSeq(lrtp->seq);
+ rtp.addCSrc(profile->csrc);
+
+ int ret = profile->pack(profile,
+ frame->data + frame->offset,
+ frame->size - frame->offset,
+ rtp);
+
+ if(ret < 0) return ret;
+
+ frame->offset += ret;
+
+ if(frame->size == frame->offset) {
+ if(profile->process_finished) {
+ profile->process_finished(profile, frame->data,
+ profile->process_finished_ptr);
+ }
+
+ profile->framelist.pop_front();
+ delete frame;
+ }
+
+ if(rtp.isValid()) {
+ size_t size = rtp.packet(packet, maxsize);
+ size = lrtp->srtp->encrypt(packet, size);
+ lrtp->seq++;
+ return size;
+ }
+
+ return 0;
+}
+
+EXPORT
+int lrtp_dequeue_frame(struct lrtp_t *lrtp,
+ char *frame, size_t maxsize,
+ unsigned int *csrc, unsigned int *ts)
+{
+ if(lrtp->framelist.size() == 0) return 0;
+
+ outputframe_t *f = lrtp->framelist.front();
+
+ if(f->size > maxsize) {
+ printf("Buffer is too small\n");
+ return -1; // Buffer too small.
+ }
+
+ memcpy(frame, f->data, f->size);
+
+ lrtp->framelist.pop_front();
+
+ free(f->data);
+ delete f;
+
+ return f->size;
+}
+
+EXPORT
+int lrtp_unpack(struct lrtp_t *lrtp, const char *packet, size_t size)
+{
+ if(!lrtp) return UNPACK_MISSING_HANDLE;
+
+ // TODO: Check lrtp magic word
+
+ char pkg[16*1024];
+ memcpy(pkg, packet, size);
+
+ size = lrtp->srtp->decrypt(pkg, size);
+
+ RTP rtp;
+ rtp.fromPacket(pkg, size);
+ std::list<csrc_t> csrcs = rtp.getCSrcs();
+ if(csrcs.size() == 0) return UNPACK_MISSING_CSRC;
+ if(csrcs.size() > 1) return UNPACK_TOO_MANY_CSRCS;
+
+ csrc_t csrc = *csrcs.begin();
+
+ struct lrtp_profile_t *profile = NULL;
+ if(lrtp->profiles.find(csrc) == lrtp->profiles.end()) {
+ return UNPACK_MISSING_PROFILE;
+ }
+
+ profile = lrtp->profiles[csrc];
+
+ std::list<outputframe_t*> framelist;
+ int ret = profile->unpack(profile, rtp, framelist);
+ lrtp->framelist.splice(lrtp->framelist.end(), framelist);
+
+ return ret;
+}
+
+#ifdef __cplusplus
+}
+#endif