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/lrtp.cc | 273 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 260 insertions(+), 13 deletions(-) (limited to 'src/lrtp.cc') 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 +#include +#include +#include -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 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 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 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 framelist; + int ret = profile->unpack(profile, rtp, framelist); + lrtp->framelist.splice(lrtp->framelist.end(), framelist); + + return ret; +} + +#ifdef __cplusplus +} +#endif -- cgit v1.2.3