diff options
Diffstat (limited to 'src/rtp_profile_l16.cc')
-rw-r--r-- | src/rtp_profile_l16.cc | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/src/rtp_profile_l16.cc b/src/rtp_profile_l16.cc new file mode 100644 index 0000000..379df1c --- /dev/null +++ b/src/rtp_profile_l16.cc @@ -0,0 +1,148 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * rtp_profile_l16.cc + * + * Mon Dec 23 14:36:50 CET 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_profile_l16.h" + +#include "rtp_profile.h" + +#include <stdio.h> +#include <string.h> + +// For ntoh et al. +#ifdef WIN32 +#include <winsock2.h> +#else +#include <arpa/inet.h> +#endif + +struct lrtp_profile_l16_t { + struct lrtp_profile_t profile; // 'Inherit' lrtp_profile_t + + unsigned short int pkg_size; + unsigned int num_channels; + bool little_endian; +}; + +int profile_l16_pack(struct lrtp_profile_t *profile, + const char *frame, size_t framesize, + RTP &rtp) +{ + struct lrtp_profile_l16_t *p = (struct lrtp_profile_l16_t *)profile; + + size_t cpsamples = p->pkg_size; + + // Calculate complete sample-channel tuples in frame. + size_t num_samples = framesize / (sizeof(short) * p->num_channels); + + if(cpsamples > num_samples) cpsamples = num_samples; + + // Convert to bytes + size_t cpsz = cpsamples * sizeof(short) * p->num_channels; + + if(p->little_endian) { + short *buf = (short*)malloc(cpsz / sizeof(short)); + for(size_t i = 0; i < cpsz / sizeof(short); i++) { + buf[i] = htons(((const short*)frame)[i]); + } + rtp.setPayload((char*)buf, cpsz); + free(buf); + } else { + rtp.setPayload(frame, cpsz); + } + + return cpsz; +} + +int profile_l16_unpack(struct lrtp_profile_t *profile, + const RTP &rtp, + std::list<outputframe_t *> &framelist) +{ + struct lrtp_profile_l16_t *p = (struct lrtp_profile_l16_t *)profile; + + outputframe_t *of = new outputframe_t(); + of->size = rtp.payloadSize(); + char *buf = (char*)malloc(of->size); + + if(p->little_endian) { + const short *frame = (const short *)rtp.payloadData(); + for(size_t i = 0; i < of->size / sizeof(short); i++) { + ((short*)buf)[i] = ntohs(frame[i]); + } + } else { + of->size = rtp.payload(buf, of->size); + } + + of->data = buf; + + framelist.push_back(of); + + return 0; +} + +void profile_l16_destroy(struct lrtp_profile_t *profile) +{ + struct lrtp_profile_l16_t *p = (struct lrtp_profile_l16_t *)profile; + delete p; +} + +struct lrtp_profile_t *profile_l16_create(struct lrtp_t *lrtp, + unsigned int csrc, + va_list vp) +{ + struct lrtp_profile_l16_t *p = new struct lrtp_profile_l16_t; + + p->profile.pack = profile_l16_pack; + p->profile.unpack = profile_l16_unpack; + p->profile.destroy = profile_l16_destroy; + + p->pkg_size = 1024; + p->little_endian = false; + p->num_channels = 1; + + while(true) { + int type = va_arg(vp, int); + if(type == OPTION_END) break; + + switch(type) { + case OPTION_L16_SAMPLES_PER_CHANNEL_PER_PACKET: + p->pkg_size = va_arg(vp, int); + break; + case OPTION_L16_CHANNELS: + p->num_channels = va_arg(vp, int); + break; + case OPTION_L16_LITTLE_ENDIAN: + p->little_endian = va_arg(vp, int); + break; + default: + // TODO: Unknown arg type + break; + } + } + + return &p->profile; +} + |