/* -*- 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 #include // For ntoh et al. #ifdef WIN32 #include #else #include #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 &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; }