diff --git a/sflphone-common/src/Codec.h b/sflphone-common/src/Codec.h new file mode 100644 index 0000000000000000000000000000000000000000..7a8552c8890d0b62ffe40f403b6b9c6860f36865 --- /dev/null +++ b/sflphone-common/src/Codec.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2009, 2008, 2009, 2010 Savoir-Faire Linux Inc. + * Author: Pierre-Luc Bacon <pierre-luc.bacon@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#ifndef __SFL_CODEC_H__ +#define __SFL_CODEC_H__ + +#include "MimeParameters.h" // TODO Move to some higher directory + +#include <tr1/memory> + +#include <cc++/digest.h> + +/** + * Interface for both audio codecs as well as video codecs. + */ +namespace sfl { +class Codec : public virtual MimeParameters +{ + public: + Codec() {}; + virtual inline ~Codec() {} + + /** + * @return The bitrate for which this codec is configured // TODO deal with VBR case. + */ + virtual double getBitRate() const = 0; + + /** + * @return The expected bandwidth used by this codec. + */ + virtual double getBandwidth() const = 0; + + /** + * @return Additional information (description) about this codec. This is meant to be shown to the user. + */ + virtual std::string getDescription() const = 0; + + /** + * @return A copy of the current codec. + */ + virtual Codec* clone() const = 0; + + /** + * Build a unique hash code for identifying the codec uniquely. + * Note that if multiple implementations of codec are provided, + * one should override this function in order to avoid conflicting + * hash codes. + * + * Hash code is a CRC32 digest made from : + * MIME "." MIME SUBTYPE "." PAYLOAD TYPE "." PAYLOAD CLOCKRATE + * + * @return a unique hash code identifying this codec. + */ + virtual std::string hashCode() const { + ost::CRC32Digest digest; + + std::ostringstream os; + os << getMimeType() + << "." << getMimeSubtype() + << "." << getPayloadType() + << "." << getClockRate(); + + std::string concat = os.str(); + + digest.putDigest ( (const unsigned char*) concat.c_str(), concat.length()); + + std::ostringstream buffer; + buffer << digest; + + return buffer.str(); + } + + void setState(bool state) { _state = state; } + + bool getState(void) { return _state; } + + private: + + bool _state; + +}; +} + +typedef sfl::Codec* create_t(); + +typedef void destroy_t (sfl::Codec*); + +#endif diff --git a/sflphone-common/src/MimeParameters.h b/sflphone-common/src/MimeParameters.h new file mode 100644 index 0000000000000000000000000000000000000000..0dce6f32fa8182d61cf67970218a36929fff7d19 --- /dev/null +++ b/sflphone-common/src/MimeParameters.h @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2009, 2008, 2009, 2010 Savoir-Faire Linux Inc. + * Author: Pierre-Luc Bacon <pierre-luc.bacon@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#ifndef __SFL_MIME_PARAMETERS_H__ +#define __SFL_MIME_PARAMETERS_H__ + +/** + * Start a new payload format definition. + */ +#define MIME_PAYLOAD_FORMAT_DEFINITION( mime, subtype, payloadType, clock ) \ + private: \ + uint8 payload; \ + public: \ + inline virtual ~MimeParameters##subtype() {}; \ + std::string getMimeType() const { \ + return std::string( mime ); \ + } \ + std::string getMimeSubtype() const { \ + return std::string( #subtype ); \ + } \ + uint8 getPayloadType() const { \ + return payload; \ + } \ + void setPayloadType(uint8 pt) { \ + payload = pt; \ + } \ + uint32 getClockRate() const { \ + return clock; \ + } \ + MimeParameters##subtype() : payload(payloadType) { + +/** + * An alias for MIME_PARAMETER_OPTIONAL + */ +#define MIME_PARAMETER(name, handler) \ + addOptionalParameter( name ); \ + addHandler( name, handler ); + +/** + * Defines an optional parameter. + */ +#define MIME_PARAMETER_OPTIONAL(name, handler) \ + addOptionalParameter( name ); \ + addHandler( name, handler ); + +/** + * Defines a required parameter. The value of this parameter + * should be obtained when sending the initial SDP offer. + */ +#define MIME_PARAMETER_REQUIRED(name, handler) \ + addRequiredParameter( name ); \ + addHandler( name, handler ); + +/** + * End a payload format definition. + */ +#define MIME_PAYLOAD_FORMAT_DEFINITION_END() \ + } + +#define MIME_PARAMETER_KEEP_IF_EQUAL MimeParameters::addParameterIfEqual + +#define MIME_PARAMETER_KEEP_MINIMUM MimeParameters::addParameterMinimum + +#define MIME_PARAMETER_KEEP_REMOTE MimeParameters::addParameterRemote + +#include "sip/Fmtp.h" + +#include <ccrtp/rtp.h> +#include <algorithm> +#include <stdexcept> +#include <vector> +#include <map> +#include <errno.h> + +namespace sfl +{ + +/** + * This exception is thrown in cases where a given format cannot + * be parsed, or required pieces of information are missing. + */ +class SdpFormatNegotiationException: public std::runtime_error +{ + public: + SdpFormatNegotiationException (const std::string& msg) : std::runtime_error (msg) {} +}; + +/** + * Interface for exposing MIME parameters in SDP offer/answer model. + */ +class MimeParameters +{ + public: + /** + * @return The mimesubtype for this codec. Eg. : "video" + */ + virtual std::string getMimeType() const = 0; + + /** + * @return The mimesubtype for this codec. Eg. : "theora" + */ + virtual std::string getMimeSubtype() const = 0; + + /** + * @return payload type numeric identifier. + */ + virtual uint8 getPayloadType() const = 0; + + /** + * @param payload The new payload to set + */ + virtual void setPayloadType(uint8 payload) = 0; + + /** + * @return RTP clock rate in Hz. + */ + virtual uint32 getClockRate() const = 0; + + /** + * @param name The name that identifies the MIME parameter. + * @param value The value this parameter should have. + */ + virtual void setParameter (const std::string& name, const std::string& value) = 0; + + /** + * @param name The name that identifies the MIME parameter. + * @return The value that is set for this parameter. + */ + virtual std::string getParameter (const std::string& name) = 0; + + /** + * @return A string containing the codec specific parameters, formatted by default as : + * "PARAM_LIST : PARAM_NAME = VALUE SEMI_COLON PARAM_LIST | PARAM_END + * PARAM_END : empty" + */ + virtual std::string getParametersFormatted() { + // TODO Instead of putting everything into the same vector, + // enforce the required vs optional aspect. Unfilled required params. should + // result in exception throwing. + std::vector<std::string> paramList = requiredParameters; + std::copy(optionalParameters.begin(), optionalParameters.end(), std::back_inserter(paramList)); + + std::string output(""); + std::vector<std::string>::iterator it; + int numberParamsAppended = 0; + for (it = paramList.begin(); it != paramList.end(); it++) { + + std::string name = *it; + std::string value = getParameter(name); + if (value != "") { + if (numberParamsAppended != 0) { + output.append("; "); + } + + output.append(name + "=" + value); + + numberParamsAppended += 1; + } + } + + return output; + } + + /** + * Calls #setParameter() in a loop for every parameters of the format object. + * @param format The format object containing the parameters to set. + */ + void setParameters(const sfl::Fmtp& format) { + sfl::Fmtp::const_iterator it; + for (it = format.begin(); it != format.end(); it++) { + _info("****************** Setting parameters"); + setParameter((*it).first, (*it).second); + } + } + + void setNegotiatedParameters(const sfl::Fmtp& format) { + negotiatedFormat = format; + } + + void applyNegotiatedParameters() { + setParameters(negotiatedFormat); + } + + protected: + sfl::Fmtp negotiatedFormat; + + /** + * @param name The name for the required parameter to add. + */ + void addRequiredParameter(const std::string& name) { + requiredParameters.push_back(name); + } + std::vector<std::string> requiredParameters; + + /** + * @param name The name for the optional parameter to add. + */ + void addOptionalParameter(const std::string& name) { + optionalParameters.push_back(name); + } + std::vector<std::string> optionalParameters; + + /** + * Negotiation handler type. + * @param localParam The local parameter. + * @param remoteParam The remote parameter. + * @param offerer The specified format for the offerer. + * @param answerer The specified format for the answerer. + * @param negotiatedFmtp The format in which to make changes, if any. + * @throw SdpFormatNegotiationException if the format can't be processed because of missing options, + * or wrong formatting. + */ + typedef void (*ParameterNegotiationHandler)( + const sfl::SdpParameter& localParam, + const sfl::SdpParameter& remoteParam, + const sfl::Fmtp& offerer, + const sfl::Fmtp& answerer, + sfl::Fmtp& negotiatedFmtp); + + std::map<std::string, ParameterNegotiationHandler> parameterHandlerTable; + + typedef std::pair<std::string, ParameterNegotiationHandler> ParameterHandlerEntry; + + typedef std::map<std::string, ParameterNegotiationHandler>::iterator ParameterHandlerIterator; + + /** + * Add a negotiation handler for the given property. + * @param name The parameter name (eg: "profile-level-id") + * @param handler A pointer to the negotiation handler function; + */ + void addHandler(const std::string& name, ParameterNegotiationHandler handler) { + parameterHandlerTable.insert(ParameterHandlerEntry(name, handler)); + } + + public: + + /** + * The default behavior if this method is not overriden is to return the format from + * the answerer. + * @param offerer The specified format for the offerer. + * @param answerer The specified format for the answerer. + * @return A format object containing the negotiated format. + * @throw SdpFormatNegotiationException if the format can't be processed because of missing options, + * or wrong formatting. + */ + virtual sfl::Fmtp negotiate(const sfl::Fmtp& offerer, const sfl::Fmtp& answerer) throw(SdpFormatNegotiationException) { + sfl::Fmtp::iterator itAnswerer; + + // This object will be built iteratively + sfl::Fmtp negotiatedFmtp(offerer.getPayloadType()); + + sfl::Fmtp::const_iterator it; + // Iterate over all of the properties in the answer + for (it = answerer.begin(); it != answerer.end(); it++) { + std::string propertyName = (*it).first; + std::string valueAnswerer = (*it).second; + + // Find the corresponding property in the offer + std::string valueOfferer; + sfl::Fmtp::const_iterator itOfferer = offerer.getParameter(propertyName); + if (it == offerer.end()) { + valueOfferer = ""; + } else { + valueOfferer = (*itOfferer).second; + } + + // Find a suitable property handler + ParameterHandlerIterator itHandler = parameterHandlerTable.find(propertyName); + if (itHandler != parameterHandlerTable.end()) { + ((*itHandler).second)(sfl::SdpParameter(propertyName, valueOfferer), + sfl::SdpParameter(propertyName, valueAnswerer), + offerer, answerer, negotiatedFmtp); + } else { + _error("Could not find any handler for property \"%s\"", propertyName.c_str()); + } + } + + return negotiatedFmtp; + } + + protected: + /** + * This handler makes + */ + static void addParameterIfEqual( + const sfl::SdpParameter& localParam, + const sfl::SdpParameter& remoteParam, + const sfl::Fmtp& offerer, + const sfl::Fmtp& answerer, + sfl::Fmtp& negotiatedFmtp) + { + if (localParam.getValue() == remoteParam.getValue()) { + negotiatedFmtp[localParam.getName()] = localParam.getValue(); + } + } + + static void addParameterMinimum( + const sfl::SdpParameter& localParam, + const sfl::SdpParameter& remoteParam, + const sfl::Fmtp& offerer, + const sfl::Fmtp& answerer, + sfl::Fmtp& negotiatedFmtp) + { + long int localValue = strtol(localParam.getValue().c_str(), NULL, 16); + if (localValue == 0 && errno == EINVAL) { + // Throw + } + + long int remoteValue = strtol(remoteParam.getValue().c_str(), NULL, 16); + if (remoteValue == 0 && errno == EINVAL) { + // Throw + } + + long int minimumValue = std::min(localValue, remoteValue); + negotiatedFmtp[localParam.getName()] = minimumValue; + } + + static void addParameterRemote( + const sfl::SdpParameter& localParam, + const sfl::SdpParameter& remoteParam, + const sfl::Fmtp& offerer, + const sfl::Fmtp& answerer, + sfl::Fmtp& negotiatedFmtp) + { + negotiatedFmtp[remoteParam.getName()] = remoteParam.getValue(); + } +}; + +} +#endif diff --git a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp index c17c0662625af1e9cb5562b30ea67a8af53ce6dd..d5514b66c0c736473322240e727bf7187b493cd9 100644 --- a/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp +++ b/sflphone-common/src/audio/audiortp/AudioRtpRecordHandler.cpp @@ -130,7 +130,7 @@ void AudioRtpRecordHandler::setRtpMedia (AudioCodec* audioCodec) // Set varios codec info to reduce indirection _audioRtpRecord._audioCodec = audioCodec; - _audioRtpRecord._codecPayloadType = audioCodec->getPayload(); + _audioRtpRecord._codecPayloadType = audioCodec->getPayloadType(); _audioRtpRecord._codecSampleRate = audioCodec->getClockRate(); _audioRtpRecord._codecFrameSize = audioCodec->getFrameSize(); _audioRtpRecord._hasDynamicPayloadType = audioCodec->hasDynamicPayload(); @@ -151,7 +151,7 @@ void AudioRtpRecordHandler::updateRtpMedia (AudioCodec *audioCodec) } _audioRtpRecord._audioCodec = audioCodec; - _audioRtpRecord._codecPayloadType = audioCodec->getPayload(); + _audioRtpRecord._codecPayloadType = audioCodec->getPayloadType(); _audioRtpRecord._codecSampleRate = audioCodec->getClockRate(); _audioRtpRecord._codecFrameSize = audioCodec->getFrameSize(); _audioRtpRecord._hasDynamicPayloadType = audioCodec->hasDynamicPayload(); @@ -297,7 +297,7 @@ int AudioRtpRecordHandler::processDataEncode (void) _audioRtpRecord.audioCodecMutex.enter(); - compSize = _audioRtpRecord._audioCodec->codecEncode (micDataEncoded, micDataConverted, nbSample * sizeof (SFLDataFormat)); + compSize = _audioRtpRecord._audioCodec->encode (micDataEncoded, micDataConverted, nbSample * sizeof (SFLDataFormat)); _audioRtpRecord.audioCodecMutex.leave(); @@ -313,7 +313,7 @@ int AudioRtpRecordHandler::processDataEncode (void) _audioRtpRecord.audioCodecMutex.enter(); // no resampling required - compSize = _audioRtpRecord._audioCodec->codecEncode (micDataEncoded, micData, nbSample * sizeof (SFLDataFormat)); + compSize = _audioRtpRecord._audioCodec->encode (micDataEncoded, micData, nbSample * sizeof (SFLDataFormat)); _audioRtpRecord.audioCodecMutex.leave(); } @@ -333,7 +333,7 @@ void AudioRtpRecordHandler::processDataDecode (unsigned char *spkrData, unsigned _audioRtpRecord.audioCodecMutex.enter(); // Return the size of data in bytes - int expandedSize = _audioRtpRecord._audioCodec->codecDecode (spkrDataDecoded , spkrData , size); + int expandedSize = _audioRtpRecord._audioCodec->decode (spkrDataDecoded , spkrData , size); _audioRtpRecord.audioCodecMutex.leave(); diff --git a/sflphone-common/src/audio/codecs/Makefile.am b/sflphone-common/src/audio/codecs/Makefile.am index 37df13bcabb39c29d72c9aadeb1b2f3650d39d30..93ea6e260db5e545b45c86861901f42fccf8a890 100644 --- a/sflphone-common/src/audio/codecs/Makefile.am +++ b/sflphone-common/src/audio/codecs/Makefile.am @@ -2,7 +2,7 @@ include $(top_srcdir)/globals.mak noinst_LTLIBRARIES = libcodecdescriptor.la -libcodecdescriptor_la_SOURCES = codecDescriptor.cpp +libcodecdescriptor_la_SOURCES = codecDescriptor.cpp audiocodec.cpp if BUILD_GSM GSM_LIB = libcodec_gsm.so @@ -10,6 +10,7 @@ libcodec_gsm_so_SOURCES = gsmcodec.cpp libcodec_gsm_so_CFLAGS = -fPIC -g -Wall libcodec_gsm_so_CXXFLAGS = -fPIC -g -Wall libcodec_gsm_so_LDFLAGS = --shared -lc -lgsm +libcodec_gsm_so_LDADD = libcodecdescriptor.la INSTALL_GSM_RULE = install-libcodec_gsm_so endif @@ -19,6 +20,7 @@ libcodec_speex_nb_so_SOURCES = speexcodec_nb.cpp libcodec_speex_nb_so_CFLAGS = -fPIC -g -Wall libcodec_speex_nb_so_CXXFLAGS = -fPIC -g -Wall $(SPEEXDSP) libcodec_speex_nb_so_LDFLAGS = --shared -lc -lspeex $(SPEEX_NIMP) +libcodec_speex_nb_so_LDADD = libcodecdescriptor.la INSTALL_SPEEX_NB_RULE = install-libcodec_speex_nb_so endif @@ -28,6 +30,7 @@ libcodec_speex_wb_so_SOURCES = speexcodec_wb.cpp libcodec_speex_wb_so_CFLAGS = -fPIC -g -Wall libcodec_speex_wb_so_CXXFLAGS = -fPIC -g -Wall $(SPEEXDSP) libcodec_speex_wb_so_LDFLAGS = --shared -lc -lspeex $(SPEEX_NIMP) +libcodec_speex_wb_so_LDADD = libcodecdescriptor.la INSTALL_SPEEX_WB_RULE = install-libcodec_speex_wb_so endif @@ -37,6 +40,7 @@ libcodec_speex_ub_so_SOURCES = speexcodec_ub.cpp libcodec_speex_ub_so_CFLAGS = -fPIC -g -Wall libcodec_speex_ub_so_CXXFLAGS = -fPIC -g -Wall $(SPEEXDSP) libcodec_speex_ub_so_LDFLAGS = --shared -lc -lspeex $(SPEEX_NIMP) +libcodec_speex_ub_so_LDADD = libcodecdescriptor.la INSTALL_SPEEX_UB_RULE = install-libcodec_speex_ub_so endif @@ -46,6 +50,7 @@ libcodec_celt_so_SOURCES = celtcodec.cpp libcodec_celt_so_CFLAGS = -fPIC -g -Wall -DBUILD_CELT_91 libcodec_celt_so_CXXFLAGS = -fPIC -g -Wall -DBUILD_CELT_91 libcodec_celt_so_LDFLAGS = --shared -lc -lcelt0 $(CELT_NIMP) +libcodec_celt_so_LDADD = libcodecdescriptor.la INSTALL_CELT_RULE = install-libcodec_celt_so endif @@ -55,6 +60,7 @@ libcodec_celt_so_SOURCES = celtcodec.cpp libcodec_celt_so_CFLAGS = -fPIC -g -Wall -DBUILD_CELT_71 libcodec_celt_so_CXXFLAGS = -fPIC -g -Wall -DBUILD_CELT_71 libcodec_celt_so_LDFLAGS = --shared -lc -lcelt0 $(CELT_NIMP) +libcodec_celt_so_LDADD = libcodecdescriptor.la INSTALL_CELT_RULE = install-libcodec_celt_so endif @@ -65,16 +71,19 @@ noinst_HEADERS = audiocodec.h codecDescriptor.h libcodec_ulaw_so_SOURCES = ulaw.cpp libcodec_ulaw_so_CFLAGS = -fPIC -g -Wall libcodec_ulaw_so_CXXFLAGS = -fPIC -g -Wall +libcodec_ulaw_so_LDADD = libcodecdescriptor.la libcodec_ulaw_so_LDFLAGS = --shared -lc libcodec_alaw_so_SOURCES = alaw.cpp libcodec_alaw_so_CFLAGS = -fPIC -g -Wall libcodec_alaw_so_CXXFLAGS = -fPIC -g -Wall +libcodec_alaw_so_LDADD = libcodecdescriptor.la libcodec_alaw_so_LDFLAGS = --shared -lc libcodec_g722_so_SOURCES = g722.cpp libcodec_g722_so_CFLAGS = -fPIC -g -Wall libcodec_g722_so_CXXFLAGS = -fPIC -g -Wall +libcodec_g722_so_LDADD = libcodecdescriptor.la libcodec_g722_so_LDFLAGS = --shared -lc install-exec-local: install-libcodec_ulaw_so install-libcodec_alaw_so install-libcodec_g722_so $(INSTALL_GSM_RULE) $(INSTALL_SPEEX_NB_RULE) $(INSTALL_SPEEX_WB_RULE) $(INSTALL_SPEEX_UB_RULE) $(INSTALL_CELT_RULE) $(INSTALL_ILBC_RULE) diff --git a/sflphone-common/src/audio/codecs/alaw.cpp b/sflphone-common/src/audio/codecs/alaw.cpp index a1e2fc8b2714b38d7f9b1d6cf768603cb76e4f01..44741d0f1df7cba721605c51c4206d238d73c4bb 100644 --- a/sflphone-common/src/audio/codecs/alaw.cpp +++ b/sflphone-common/src/audio/codecs/alaw.cpp @@ -49,7 +49,7 @@ class Alaw : public AudioCodec virtual ~Alaw() {} - virtual int codecDecode (short *dst, unsigned char *src, unsigned int size) { + virtual int decode (short *dst, unsigned char *src, unsigned int size) { int16* end = dst+size; while (dst<end) @@ -58,7 +58,7 @@ class Alaw : public AudioCodec return size<<1; } - virtual int codecEncode (unsigned char *dst, short *src, unsigned int size) { + virtual int encode (unsigned char *dst, short *src, unsigned int size) { size >>= 1; uint8* end = dst+size; @@ -129,16 +129,30 @@ class Alaw : public AudioCodec return a^0x55; // A-law has alternate bits inverted for transmission } + /** + * @Override + */ + std::string getDescription() const { + return "audio/PCMA 8000 (\"alaw\") codec."; + } + + /** + * @Override + */ + Alaw* clone() const { + return new Alaw (*this); + } + }; // the class factories -extern "C" AudioCodec* create() +extern "C" sfl::Codec* create() { return new Alaw (8); } -extern "C" void destroy (AudioCodec* a) +extern "C" void destroy (sfl::Codec* a) { delete a; } diff --git a/sflphone-common/src/audio/codecs/audiocodec.cpp b/sflphone-common/src/audio/codecs/audiocodec.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2c3b720161a931a5aaf55af685a112058eced98c --- /dev/null +++ b/sflphone-common/src/audio/codecs/audiocodec.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2009, 2008, 2009, 2010 Savoir-Faire Linux Inc. + * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> + * + * Mostly borrowed from asterisk's sources (Steve Underwood <steveu@coppice.org>) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Additional permission under GNU GPL version 3 section 7: + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. + * grants you additional permission to convey the resulting work. + * Corresponding Source for a non-source form of such a combination + * shall include the source code for the parts of OpenSSL used as well + * as that of the covered work. + */ + +#include "audiocodec.h" + +AudioCodec::AudioCodec (uint8 payload, const std::string &codecName) : + _codecName (codecName), _clockRate (8000), _channel (1), _bitrate (0.0), + _bandwidth (0), _payload (payload), _hasDynamicPayload (false) +{ + init (payload, _clockRate); +} + +AudioCodec::AudioCodec (const AudioCodec& codec) : + _codecName (codec._codecName), _clockRate (codec._clockRate), _channel ( + codec._channel), _bitrate (codec._bitrate), _bandwidth ( + codec._bandwidth), _payload (codec._payload), _hasDynamicPayload ( + false) +{ + init (codec._payload, codec._clockRate); +} + +void AudioCodec::init (uint8 payloadType, uint32 clockRate) +{ + _payloadFormat = new ost::DynamicPayloadFormat (payloadType, clockRate); + + _hasDynamicPayload = (_payload >= 96 && _payload <= 127) ? true : false; + + // If g722 (payload 9), we need to init libccrtp symetric sessions with using + // dynamic payload format. This way we get control on rtp clockrate. + + if (_payload == 9) { + _hasDynamicPayload = true; + } +} + +std::string AudioCodec::getMimeType() const +{ + return "audio"; +} + +std::string AudioCodec::getMimeSubtype() const +{ + return _codecName; +} + +const ost::PayloadFormat& AudioCodec::getPayloadFormat() +{ + return (*_payloadFormat); +} + +uint8 AudioCodec::getPayloadType (void) const +{ + return _payload; +} + +bool AudioCodec::hasDynamicPayload (void) +{ + return _hasDynamicPayload; +} + +uint32 AudioCodec::getClockRate (void) const +{ + return _clockRate; +} + +unsigned AudioCodec::getFrameSize (void) const +{ + return _frameSize; +} + +uint8 AudioCodec::getChannel (void) const +{ + return _channel; +} + +double AudioCodec::getBitRate (void) const +{ + return _bitrate; +} + +double AudioCodec::getBandwidth (void) const +{ + return _bandwidth; +} diff --git a/sflphone-common/src/audio/codecs/audiocodec.h b/sflphone-common/src/audio/codecs/audiocodec.h index 25d2e88fda6974e77a13a2727c36fcc482c0f3b4..3ded1b3dd41f51eda7a41e04ec0bcba802a0b157 100644 --- a/sflphone-common/src/audio/codecs/audiocodec.h +++ b/sflphone-common/src/audio/codecs/audiocodec.h @@ -1,8 +1,8 @@ /* - * Copyright (C) 2004, 2005, 2006, 2009, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc. + * Copyright (C) 2004, 2005, 2006, 2009, 2008, 2009, 2010 Savoir-Faire Linux Inc. * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> * - * Motly borrowed from asterisk's sources (Steve Underwood <steveu@coppice.org>) + * Mostly borrowed from asterisk's sources (Steve Underwood <steveu@coppice.org>) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,105 +29,163 @@ * shall include the source code for the parts of OpenSSL used as well * as that of the covered work. */ - -#ifndef _CODEC_AUDIO_H -#define _CODEC_AUDIO_H +#ifndef __AUDIO_CODEC_H__ +#define __AUDIO_CODEC_H__ #include <string> #include <iostream> #include <dlfcn.h> -class AudioCodec -{ - protected: - /** Holds SDP-compliant codec name */ - std::string _codecName; // what we put inside sdp - - /** Clock rate or sample rate of the codec, in Hz */ - int _clockRate; - - /** Number of channel 1 = mono, 2 = stereo */ - int _channel; +#include "Codec.h" - /** codec frame size in samples*/ - int _frameSize; +class AudioCodec : public sfl::Codec // TODO Move into the "sfl" namespace +{ + public: + AudioCodec (uint8 payload, const std::string &codecName); - /** Bitrate */ - double _bitrate; - /** Bandwidth */ - double _bandwidth; + /** + * Copy constructor. + */ + AudioCodec (const AudioCodec& codec); - protected: - bool _hasDynamicPayload; + virtual ~AudioCodec() {} - private: - int _payload; - bool _state; + /** + * @Override + */ + std::string getMimeType() const; - public: - AudioCodec (int payload, const std::string &codecName) - : _codecName (codecName), _clockRate (8000), _channel (1), _bitrate (0.0),_bandwidth (0), _hasDynamicPayload (false), _payload (payload),_state (true) { + /** + * @Override + */ + std::string getMimeSubtype() const; - _hasDynamicPayload = (_payload >= 96 && _payload <= 127) ? true : false; - } + /** + * @Override + */ + const ost::PayloadFormat& getPayloadFormat(); - AudioCodec (const AudioCodec& codec) - : _codecName (codec._codecName), _clockRate (codec._clockRate), _channel (codec._channel), _bitrate (codec._bitrate),_bandwidth (codec._bandwidth), _hasDynamicPayload (false), _payload (codec._payload),_state (true) { + /** + * @Override + */ + void setParameter (const std::string& name, const std::string& value) {}; - _hasDynamicPayload = (_payload >= 96 && _payload <= 127) ? true : false; - } + /** + * @Override + */ + std::string getParameter (const std::string& name) { + return ""; + }; - virtual ~AudioCodec() { - } /** * Decode an input buffer and fill the output buffer with the decoded data * @return the number of bytes decoded */ - virtual int codecDecode (short *, unsigned char *, unsigned int) = 0; + virtual int decode (short *, unsigned char *, unsigned int) = 0; /** * Encode an input buffer and fill the output buffer with the encoded data * @return the number of bytes encoded */ - virtual int codecEncode (unsigned char *, short *, unsigned int) = 0; + virtual int encode (unsigned char *, short *, unsigned int) = 0; + /** + * @Override + */ + uint8 getPayloadType() const ; - /** Value used for SDP negotiation */ - std::string getCodecName (void) { - return _codecName; - } - int getPayload (void) { - return _payload; - } - bool hasDynamicPayload (void) { - return _hasDynamicPayload; - } - int getClockRate (void) { - return _clockRate; + /** + * @Override + */ + void setPayloadType(uint8 pt) { + _payload = pt; } - int getFrameSize (void) { - return _frameSize; + + /** + * @return true if this payload is a dynamic one. + */ + bool hasDynamicPayload(); + + /** + * @Override + */ + uint32 getClockRate() const; + + /** + * @return the number of audio channels. + */ + uint8 getChannel() const; + + /** + * @Override + */ + double getBitRate() const; + + /** + * @Override + */ + double getBandwidth() const; + + /** + * @return the framing size for this codec. + */ + unsigned int getFrameSize() const; + + /** + * @Override + */ + virtual AudioCodec* clone() const = 0; + + protected: + /** Holds SDP-compliant codec name */ + std::string _codecName; // what we put inside sdp + + /** Clock rate or sample rate of the codec, in Hz */ + uint32 _clockRate; + + /** Number of channel 1 = mono, 2 = stereo */ + uint8 _channel; + + /** codec frame size in samples*/ + unsigned _frameSize; + + /** Bitrate */ + double _bitrate; + + /** Bandwidth */ + double _bandwidth; + + bool _hasDynamicPayload; + + void setCodecName (const std::string& codecName) { + _codecName = codecName; } - int getChannel (void) { - return _channel; + + void setClockRate (uint32 rate) { + _clockRate = rate; } - bool getState (void) { - return _state; + + void setChannel (uint8 channel) { + _channel = channel; } - void setState (bool b) { - _state = b; + + void setFrameSize (unsigned size) { + _frameSize = size; } - double getBitRate (void) { - return _bitrate; + + void setBitrate (double rate) { + _bitrate = rate; } - double getBandwidth (void) { - return _bandwidth; + + void setBandwidth (double bandwidth) { + _bandwidth = bandwidth; } + private: + uint8 _payload; -}; + ost::DynamicPayloadFormat* _payloadFormat; -// the types of the class factories -typedef AudioCodec* create_t(); -typedef void destroy_t (AudioCodec*); + void init (uint8 payloadType, uint32 clockRate); +}; #endif diff --git a/sflphone-common/src/audio/codecs/celtcodec.cpp b/sflphone-common/src/audio/codecs/celtcodec.cpp index 92ac63c0925ef556c59002c116b6e69192f86018..17f9577f5d29aa983c6d4acb7fe8667d6b2d1cfa 100644 --- a/sflphone-common/src/audio/codecs/celtcodec.cpp +++ b/sflphone-common/src/audio/codecs/celtcodec.cpp @@ -125,7 +125,7 @@ class Celt : public AudioCodec celt_mode_destroy (_mode); } - virtual int codecDecode (short *dst, unsigned char *src, unsigned int size) { + virtual int decode (short *dst, unsigned char *src, unsigned int size) { #ifdef BUILD_CELT_91 // == 91 int err = 0; err = celt_decode (_dec, src, size, (celt_int16*) dst, size); @@ -137,7 +137,7 @@ class Celt : public AudioCodec return _frameSize * sizeof (celt_int16); } - virtual int codecEncode (unsigned char *dst, short *src, unsigned int size) { + virtual int encode (unsigned char *dst, short *src, unsigned int size) { int len = 0; #ifdef BUILD_CELT_91// == 91 len = celt_encode (_enc, (celt_int16*) src, size, dst, 40); @@ -149,6 +149,21 @@ class Celt : public AudioCodec return len; } + /** + * @Override + */ + std::string getDescription() const { + return "audio/celt 32000 (\"HD\") codec. Based on libcelt, by Jean-Marc Valin."; + } + + /** + * @Override + */ + Celt* clone() const { + return new Celt (*this); + } + + private: CELTMode *_mode; @@ -162,12 +177,12 @@ class Celt : public AudioCodec }; // the class factories -extern "C" AudioCodec* create() +extern "C" sfl::Codec* create() { return new Celt (115); } -extern "C" void destroy (AudioCodec* a) +extern "C" void destroy (sfl::Codec* a) { delete a; } diff --git a/sflphone-common/src/audio/codecs/codecDescriptor.cpp b/sflphone-common/src/audio/codecs/codecDescriptor.cpp index f14c2dc4b6afdba8cf29f7cbdf93d14550fd1c96..e1e895cc5ab0c01a6b483dcfd2b78ce732caa7bc 100644 --- a/sflphone-common/src/audio/codecs/codecDescriptor.cpp +++ b/sflphone-common/src/audio/codecs/codecDescriptor.cpp @@ -36,6 +36,7 @@ #include "codecDescriptor.h" + CodecDescriptor::CodecDescriptor() : _CodecsMap(), _defaultCodecOrder(), _Cache(), _nbCodecs(), _CodecInMemory() { } @@ -45,22 +46,23 @@ CodecDescriptor::~CodecDescriptor() } -void -CodecDescriptor::deleteHandlePointer (void) -{ - _debug ("CodecDesccriptor: Delete codec handle pointers"); - - for (int i = 0 ; (unsigned int) i < _CodecInMemory.size() ; i++) { - unloadCodec (_CodecInMemory[i]); - } +//std::vector<std::string> CodecDescriptor::getAllMimeSubtypes() +//{ +// std::vector<std::string> output; +// IdentifierToCodecInstanceMapIterator it; +// +// for (it = _codecsMap.begin(); it != _codecsMap.end(); it++) { +// output.push_back ( ( (*it).second)->getMimeSubtype()); +// } +// +// return output; +//} - _CodecInMemory.clear(); -} void CodecDescriptor::init() { - std::vector<AudioCodec*> CodecDynamicList = scanCodecDirectory(); + std::vector<sfl::Codec*> CodecDynamicList = scanCodecDirectory(); _nbCodecs = CodecDynamicList.size(); if (_nbCodecs <= 0) { @@ -70,8 +72,9 @@ CodecDescriptor::init() int i; for (i = 0 ; i < _nbCodecs ; i++) { - _CodecsMap[ (AudioCodecType) CodecDynamicList[i]->getPayload() ] = CodecDynamicList[i]; - _debug ("CodecDescriptor: %s" , CodecDynamicList[i]->getCodecName().c_str()); + _CodecsMap[ (AudioCodecType) CodecDynamicList[i]->getPayloadType() ] = CodecDynamicList[i]; + _debug ("CodecDescriptor: %s" , CodecDynamicList[i]->getMimeSubtype().c_str()); + } } @@ -95,19 +98,19 @@ CodecDescriptor::getCodecName (AudioCodecType payload) CodecsMap::iterator iter = _CodecsMap.find (payload); if (iter!=_CodecsMap.end()) { - return (iter->second->getCodecName()); + return (iter->second->getMimeSubtype()); } return resNull; } -AudioCodec* +sfl::Codec* CodecDescriptor::getCodec (AudioCodecType payload) { CodecsMap::iterator iter = _CodecsMap.find (payload); if (iter!=_CodecsMap.end()) { - return (iter->second); + return static_cast<AudioCodec *>(iter->second); } _error ("CodecDescriptor: Error cannont found codec %i in _CodecsMap from codec descriptor", payload); @@ -170,10 +173,22 @@ void CodecDescriptor::saveActiveCodecs (const std::vector<std::string>& list) } } -std::vector<AudioCodec*> CodecDescriptor::scanCodecDirectory (void) +void +CodecDescriptor::deleteHandlePointer (void) +{ + _debug ("CodecDesccriptor: Delete codec handle pointers"); + + for (int i = 0 ; (unsigned int) i < _CodecInMemory.size() ; i++) { + unloadCodec (_CodecInMemory[i]); + } + + _CodecInMemory.clear(); +} + +std::vector<sfl::Codec*> CodecDescriptor::scanCodecDirectory (void) { - std::vector<AudioCodec*> codecs; + std::vector<sfl::Codec*> codecs; std::string tmp; int i; @@ -187,7 +202,7 @@ std::vector<AudioCodec*> CodecDescriptor::scanCodecDirectory (void) std::string dirStr = dirToScan[i]; _debug ("CodecDescriptor: Scanning %s to find audio codecs....", dirStr.c_str()); DIR *dir = opendir (dirStr.c_str()); - AudioCodec* audioCodec; + sfl::Codec* audioCodec; if (dir) { dirent *dirStruct; @@ -211,7 +226,7 @@ std::vector<AudioCodec*> CodecDescriptor::scanCodecDirectory (void) return codecs; } -AudioCodec* CodecDescriptor::loadCodec (std::string path) +sfl::Codec* CodecDescriptor::loadCodec (std::string path) { CodecHandlePointer p; @@ -228,7 +243,7 @@ AudioCodec* CodecDescriptor::loadCodec (std::string path) if (dlerror()) cerr << dlerror() << '\n'; - AudioCodec* a = createCodec(); + sfl::Codec* a = createCodec(); p = CodecHandlePointer (a, codecHandle); @@ -252,7 +267,7 @@ void CodecDescriptor::unloadCodec (CodecHandlePointer p) dlclose (p.second); } -AudioCodec* CodecDescriptor::instantiateCodec (AudioCodecType payload) +sfl::Codec* CodecDescriptor::instantiateCodec (AudioCodecType payload) { using std::cerr; @@ -260,13 +275,13 @@ AudioCodec* CodecDescriptor::instantiateCodec (AudioCodecType payload) std::vector< CodecHandlePointer >::iterator iter = _CodecInMemory.begin(); while (iter != _CodecInMemory.end()) { - if (iter->first->getPayload() == payload) { + if (iter->first->getPayloadType() == payload) { create_t* createCodec = (create_t*) dlsym (iter->second , "create"); if (dlerror()) cerr << dlerror() << '\n'; - AudioCodec* a = createCodec(); + sfl::Codec* a = createCodec(); return a; } @@ -279,7 +294,7 @@ AudioCodec* CodecDescriptor::instantiateCodec (AudioCodecType payload) -AudioCodec* CodecDescriptor::getFirstCodecAvailable (void) +sfl::Codec* CodecDescriptor::getFirstCodecAvailable (void) { CodecsMap::iterator iter = _CodecsMap.begin(); diff --git a/sflphone-common/src/audio/codecs/codecDescriptor.h b/sflphone-common/src/audio/codecs/codecDescriptor.h index 1f4a7b38a9bad6717afec56a40e35b54f5a9a042..c82aba70e99dc2b00c5d01eeeb804d5d1c5d12fb 100644 --- a/sflphone-common/src/audio/codecs/codecDescriptor.h +++ b/sflphone-common/src/audio/codecs/codecDescriptor.h @@ -39,12 +39,12 @@ #include "global.h" #include "user_cfg.h" -#include "audio/codecs/audiocodec.h" +#include "audiocodec.h" /** Enable us to keep the handle pointer on the codec dynamicaly loaded so that we could destroy when we dont need it anymore */ -typedef std::pair<AudioCodec* , void*> CodecHandlePointer; +typedef std::pair<sfl::Codec* , void*> CodecHandlePointer; /** Maps a pointer on an audiocodec object to a payload */ -typedef std::map<AudioCodecType , AudioCodec*> CodecsMap; +typedef std::map<AudioCodecType , sfl::Codec*> CodecsMap; /** A codec is identified by its payload. A payload is associated with a name. */ typedef std::map<AudioCodecType, std::string> CodecMap; @@ -87,7 +87,7 @@ class CodecDescriptor * @param payload The payload looked for * @return AudioCodec* A pointer on a AudioCodec object */ - AudioCodec* getCodec (AudioCodecType payload); + sfl::Codec* getCodec (AudioCodecType payload); /** * Initialiaze the map with all the supported codecs, even those inactive @@ -147,13 +147,13 @@ class CodecDescriptor * i.e the one with the lowest payload * @return AudioCodec The pointer on the codec object */ - AudioCodec* getFirstCodecAvailable (void); + sfl::Codec* getFirstCodecAvailable (void); /** * Instantiate a codec, used in AudioRTP to get an instance of Codec per call * @param CodecHandlePointer The map containing the pointer on the object and the pointer on the handle function */ - AudioCodec* instantiateCodec (AudioCodecType payload); + sfl::Codec* instantiateCodec (AudioCodecType payload); /** * For a given codec, return its specification @@ -178,14 +178,14 @@ class CodecDescriptor * And load the dynamic library * @return std::vector<AudioCodec*> The list of the codec object successfully loaded in memory */ - std::vector<AudioCodec *> scanCodecDirectory (void); + std::vector<sfl::Codec *> scanCodecDirectory (void); /** * Load a codec * @param std::string The path of the shared ( dynamic ) library. * @return AudioCodec* the pointer of the object loaded. */ - AudioCodec* loadCodec (std::string); + sfl::Codec* loadCodec (std::string); /** * Unload a codec diff --git a/sflphone-common/src/audio/codecs/g722.cpp b/sflphone-common/src/audio/codecs/g722.cpp index 3e5c8bf6017b897c2d20671e447f32aaa98c6a9a..0335aea92a7249a8be677f676f4c8c1d2b8b733f 100644 --- a/sflphone-common/src/audio/codecs/g722.cpp +++ b/sflphone-common/src/audio/codecs/g722.cpp @@ -71,7 +71,7 @@ class G722 : public AudioCodec g722_encode_release(); } - virtual int codecDecode (short *dst, unsigned char *src, unsigned int size) { + virtual int decode (short *dst, unsigned char *src, unsigned int size) { int in_byte = size; int out_samples; @@ -81,7 +81,7 @@ class G722 : public AudioCodec return out_samples * 2; } - virtual int codecEncode (unsigned char *dst, short *src, unsigned int size) { + virtual int encode (unsigned char *dst, short *src, unsigned int size) { // 2 bytes per sample (int16) int in_samples = size / 2; @@ -822,6 +822,21 @@ class G722 : public AudioCodec } + /** + * @Override + */ + std::string getDescription() const { + return "G722 codec. Most of the code comes from Steve Underwood (<steveu@coppice.org>) for the Asterisk project."; + } + + /** + * @Override + */ + G722* clone() const { + return new G722 (*this); + } + + private: g722_decode_state_t *decode_s; @@ -830,12 +845,12 @@ class G722 : public AudioCodec }; // the class factories -extern "C" AudioCodec* create() +extern "C" sfl::Codec* create() { return new G722 (9); } -extern "C" void destroy (AudioCodec* a) +extern "C" void destroy (sfl::Codec* a) { delete a; } diff --git a/sflphone-common/src/audio/codecs/gsmcodec.cpp b/sflphone-common/src/audio/codecs/gsmcodec.cpp index 76735aaa3eb5a78c14e3f85f9d602d40b06e3777..8ab18aa41872b16edc4de9bd367cb7878641c200 100644 --- a/sflphone-common/src/audio/codecs/gsmcodec.cpp +++ b/sflphone-common/src/audio/codecs/gsmcodec.cpp @@ -68,7 +68,7 @@ class Gsm : public AudioCodec gsm_destroy (_encode_gsmhandle); } - virtual int codecDecode (short * dst, unsigned char * src, unsigned int size) { + virtual int decode (short * dst, unsigned char * src, unsigned int size) { // _debug("Decoded by gsm "); (void) size; @@ -78,7 +78,7 @@ class Gsm : public AudioCodec return 320; } - virtual int codecEncode (unsigned char * dst, short * src, unsigned int size) { + virtual int encode (unsigned char * dst, short * src, unsigned int size) { // _debug("Encoded by gsm "); (void) size; @@ -86,17 +86,32 @@ class Gsm : public AudioCodec return 33; } + /** + * @Override + */ + std::string getDescription() const { + return "GSM codec. Based on libgsm, (C) Jutta Degener and Carsten Bormann, Technische Universitaet Berlin."; + } + + /** + * @Override + */ + Gsm* clone() const { + return new Gsm (*this); + } + + private: gsm _decode_gsmhandle; gsm _encode_gsmhandle; }; -extern "C" AudioCodec* create() +extern "C" sfl::Codec* create() { return new Gsm (3); } -extern "C" void destroy (AudioCodec* a) +extern "C" void destroy (sfl::Codec* a) { delete a; } diff --git a/sflphone-common/src/audio/codecs/speexcodec_nb.cpp b/sflphone-common/src/audio/codecs/speexcodec_nb.cpp index 5f797f428242bc2dc5391171aca4aa3dc7f83fc2..8a22ab9d5ab62b39ceb611d4f2f1dba78addf7c8 100644 --- a/sflphone-common/src/audio/codecs/speexcodec_nb.cpp +++ b/sflphone-common/src/audio/codecs/speexcodec_nb.cpp @@ -95,7 +95,7 @@ class Speex : public AudioCodec _speex_enc_state = 0; } - virtual int codecDecode (short *dst, unsigned char *src, unsigned int size) { + virtual int decode (short *dst, unsigned char *src, unsigned int size) { // int ratio = 320 / _speex_frame_size; speex_bits_read_from (&_speex_dec_bits, (char*) src, size); @@ -105,7 +105,7 @@ class Speex : public AudioCodec return _frameSize * 2; } - virtual int codecEncode (unsigned char *dst, short *src, unsigned int size) { + virtual int encode (unsigned char *dst, short *src, unsigned int size) { speex_bits_reset (&_speex_enc_bits); speex_encode_int (_speex_enc_state, src, &_speex_enc_bits); @@ -114,6 +114,21 @@ class Speex : public AudioCodec return nbBytes; } + /** + * @Override + */ + std::string getDescription() const { + return "audio/speex 8000 (\"narrow band\") codec. Based on libspeex, by Jean-Marc Valin."; + } + + /** + * @Override + */ + Speex* clone() const { + return new Speex (*this); + } + + private: const SpeexMode* _speexModePtr; SpeexBits _speex_dec_bits; @@ -124,12 +139,12 @@ class Speex : public AudioCodec }; // the class factories -extern "C" AudioCodec* create() +extern "C" sfl::Codec* create() { return new Speex (110); } -extern "C" void destroy (AudioCodec* a) +extern "C" void destroy (sfl::Codec* a) { delete a; } diff --git a/sflphone-common/src/audio/codecs/speexcodec_ub.cpp b/sflphone-common/src/audio/codecs/speexcodec_ub.cpp index f1f88cd746d1003ac963a610d5cc20cf6666d78f..3a9cebee7adcda38d224de9ad58b20e5ceb1660c 100644 --- a/sflphone-common/src/audio/codecs/speexcodec_ub.cpp +++ b/sflphone-common/src/audio/codecs/speexcodec_ub.cpp @@ -96,7 +96,7 @@ class Speex : public AudioCodec } - virtual int codecDecode (short *dst, unsigned char *src, unsigned int size) { + virtual int decode (short *dst, unsigned char *src, unsigned int size) { // int ratio = 320 / _speex_frame_size; speex_bits_read_from (&_speex_dec_bits, (char*) src, size); @@ -106,7 +106,7 @@ class Speex : public AudioCodec return _frameSize * 2; } - virtual int codecEncode (unsigned char *dst, short *src, unsigned int size) { + virtual int encode (unsigned char *dst, short *src, unsigned int size) { speex_bits_reset (&_speex_enc_bits); speex_encode_int (_speex_enc_state, src, &_speex_enc_bits); @@ -116,6 +116,21 @@ class Speex : public AudioCodec return nbBytes; } + /** + * @Override + */ + std::string getDescription() const { + return "audio/speex 32000 (\"ultra wide band\") codec. Based on libspeex, by Jean-Marc Valin."; + } + + /** + * @Override + */ + Speex* clone() const { + return new Speex (*this); + } + + private: const SpeexMode* _speexModePtr; SpeexBits _speex_dec_bits; @@ -126,12 +141,12 @@ class Speex : public AudioCodec }; // the class factories -extern "C" AudioCodec* create() +extern "C" sfl::Codec* create() { return new Speex (112); } -extern "C" void destroy (AudioCodec* a) +extern "C" void destroy (sfl::Codec* a) { delete a; } diff --git a/sflphone-common/src/audio/codecs/speexcodec_wb.cpp b/sflphone-common/src/audio/codecs/speexcodec_wb.cpp index 693f70f6988cef80b850b496f9314bfe17119bdc..3969ee94a39d2ddc57d10a7be561b9135350cd64 100644 --- a/sflphone-common/src/audio/codecs/speexcodec_wb.cpp +++ b/sflphone-common/src/audio/codecs/speexcodec_wb.cpp @@ -94,7 +94,7 @@ class Speex : public AudioCodec } - virtual int codecDecode (short *dst, unsigned char *src, unsigned int size) { + virtual int decode (short *dst, unsigned char *src, unsigned int size) { // int ratio = 320 / _speex_frame_size; @@ -105,7 +105,7 @@ class Speex : public AudioCodec return _frameSize * 2; } - virtual int codecEncode (unsigned char *dst, short *src, unsigned int size) { + virtual int encode (unsigned char *dst, short *src, unsigned int size) { speex_bits_reset (&_speex_enc_bits); //printf ("Codec::codecEncode() size %i\n", size); @@ -115,6 +115,20 @@ class Speex : public AudioCodec return nbBytes; } + /** + * @Override + */ + std::string getDescription() const { + return "audio/speex 16000 (\"wide band\") codec. Based on libspeex, by Jean-Marc Valin."; + } + + /** + * @Override + */ + Speex* clone() const { + return new Speex (*this); + } + private: const SpeexMode* _speexModePtr; SpeexBits _speex_dec_bits; @@ -125,12 +139,12 @@ class Speex : public AudioCodec }; // the class factories -extern "C" AudioCodec* create() +extern "C" sfl::Codec* create() { return new Speex (111); } -extern "C" void destroy (AudioCodec* a) +extern "C" void destroy (sfl::Codec* a) { delete a; } diff --git a/sflphone-common/src/audio/codecs/ulaw.cpp b/sflphone-common/src/audio/codecs/ulaw.cpp index 74614e93f2076ae0919bf459155aa9529464e5c7..3e40b8b8a9861c16e0123bb7c4b5408de4a45ace 100644 --- a/sflphone-common/src/audio/codecs/ulaw.cpp +++ b/sflphone-common/src/audio/codecs/ulaw.cpp @@ -49,7 +49,7 @@ class Ulaw : public AudioCodec _hasDynamicPayload = false; } - virtual int codecDecode (short *dst, unsigned char *src, unsigned int size) { + virtual int decode (short *dst, unsigned char *src, unsigned int size) { int16* end = dst+size; while (dst<end) @@ -58,7 +58,7 @@ class Ulaw : public AudioCodec return size<<1; } - virtual int codecEncode (unsigned char *dst, short *src, unsigned int size) { + virtual int encode (unsigned char *dst, short *src, unsigned int size) { size >>= 1; uint8* end = dst+size; @@ -123,15 +123,30 @@ class Ulaw : public AudioCodec return u; } + + /** + * @Override + */ + std::string getDescription() const { + return "audio/PCMU 8000 (\"ulaw\") codec."; + } + + /** + * @Override + */ + Ulaw* clone() const { + return new Ulaw (*this); + } + }; // the class factories -extern "C" AudioCodec* create() +extern "C" sfl::Codec* create() { return new Ulaw (0); } -extern "C" void destroy (AudioCodec* a) +extern "C" void destroy (sfl::Codec* a) { delete a; } diff --git a/sflphone-common/src/audio/sound/audiofile.cpp b/sflphone-common/src/audio/sound/audiofile.cpp index fa764df75b4d88c0863b4c7aa8cf4174941bb277..adc132d8e6c6a2da11d5f6b73c588dafa8d9b6df 100644 --- a/sflphone-common/src/audio/sound/audiofile.cpp +++ b/sflphone-common/src/audio/sound/audiofile.cpp @@ -111,7 +111,7 @@ RawFile::loadFile (const std::string& filename, AudioCodec* codec , unsigned int // expandedsize should be exactly two time more, else failed int16 monoBuffer[length]; - int expandedsize = (int) _codec->codecDecode (monoBuffer, (unsigned char *) fileBuffer, length); + int expandedsize = (int) _codec->decode (monoBuffer, (unsigned char *) fileBuffer, length); if (expandedsize != length*2) { _debug ("Audio file error on loading audio file!"); diff --git a/sflphone-common/src/iax/iaxvoiplink.cpp b/sflphone-common/src/iax/iaxvoiplink.cpp index 079a968f2b23c7c47adf9020d2fb8e42ce0e2dea..2c3a0b1a7a9707b51178657ab35f301d06a049a7 100644 --- a/sflphone-common/src/iax/iaxvoiplink.cpp +++ b/sflphone-common/src/iax/iaxvoiplink.cpp @@ -330,7 +330,7 @@ IAXVoIPLink::sendAudioFromMic (void) if (callIsActive) { - ac = currentCall->getCodecMap().getCodec (currentCall->getAudioCodec()); + ac = static_cast<AudioCodec *>(currentCall->getCodecMap().getCodec (currentCall->getAudioCodec())); // Send sound here @@ -370,12 +370,12 @@ IAXVoIPLink::sendAudioFromMic (void) nbSample_ = converter->downsampleData (micData , micDataConverted , (int) ac->getClockRate(), _mainBufferSampleRate, nbSample_); // for the mono: range = 0 to IAX_FRAME2SEND * sizeof(int16) - compSize = ac->codecEncode (micDataEncoded, micDataConverted , nbSample_*sizeof (int16)); + compSize = ac->encode (micDataEncoded, micDataConverted , nbSample_*sizeof (int16)); } else { // for the mono: range = 0 to IAX_FRAME2SEND * sizeof(int16) - compSize = ac->codecEncode (micDataEncoded, micData, nbSample_*sizeof (int16)); + compSize = ac->encode (micDataEncoded, micData, nbSample_*sizeof (int16)); } @@ -712,10 +712,10 @@ IAXVoIPLink::getCurrentCodecName() call = getIAXCall (Manager::instance().getCurrentCallId()); if (call) - ac = call->getCodecMap().getCodec (call->getAudioCodec()); + ac = static_cast<AudioCodec *>(call->getCodecMap().getCodec (call->getAudioCodec())); if (ac) - name = ac->getCodecName(); + name = ac->getMimeSubtype(); return name; } @@ -975,7 +975,7 @@ IAXVoIPLink::iaxHandleVoiceEvent (iax_event* event, IAXCall* call) return; } - ac = call->getCodecMap ().getCodec (call->getAudioCodec ()); + ac = static_cast<AudioCodec *>(call->getCodecMap ().getCodec (call->getAudioCodec ())); if (!ac) return; @@ -1013,7 +1013,7 @@ IAXVoIPLink::iaxHandleVoiceEvent (iax_event* event, IAXCall* call) size = max; } - expandedSize = ac->codecDecode (spkrDataDecoded , data , size); + expandedSize = ac->decode (spkrDataDecoded , data , size); nbInt16 = expandedSize/sizeof (int16); diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp index fedd05199306aac5ac637953480425a776a97863..d7c013bcf6f532d796e00432e606016d9a2ad109 100644 --- a/sflphone-common/src/managerimpl.cpp +++ b/sflphone-common/src/managerimpl.cpp @@ -2218,7 +2218,7 @@ void ManagerImpl::ringtone (const AccountID& accountID) layer = audiolayer->getLayerType(); samplerate = audiolayer->getSampleRate(); - codecForTone = _codecDescriptorMap.getFirstCodecAvailable(); + codecForTone = static_cast<AudioCodec *>(_codecDescriptorMap.getFirstCodecAvailable()); _toneMutex.enterMutex(); @@ -2237,7 +2237,7 @@ void ManagerImpl::ringtone (const AccountID& accountID) loadFile = false; - _debug ("Manager: ringChoice: %s, codecForTone: %d, samplerate %d", ringchoice.c_str(), codecForTone->getPayload(), samplerate); + _debug ("Manager: ringChoice: %s, codecForTone: %d, samplerate %d", ringchoice.c_str(), codecForTone->getPayloadType(), samplerate); if (_audiofile) loadFile = _audiofile->loadFile (ringchoice, codecForTone, samplerate); diff --git a/sflphone-common/src/sip/sdp.cpp b/sflphone-common/src/sip/sdp.cpp index abb2e472b1dd5654928bf76365538536b2f35925..f0a65ed87494bcd83d913c250a87da7a16fcf9e4 100644 --- a/sflphone-common/src/sip/sdp.cpp +++ b/sflphone-common/src/sip/sdp.cpp @@ -70,7 +70,7 @@ void Sdp::set_media_descriptor_line (sdpMedia *media, pjmedia_sdp_media** p_med) pjmedia_sdp_media* med; pjmedia_sdp_rtpmap rtpmap; pjmedia_sdp_attr *attr; - AudioCodec *codec; + sfl::Codec *codec; int count, i; std::string tmp; @@ -99,7 +99,7 @@ void Sdp::set_media_descriptor_line (sdpMedia *media, pjmedia_sdp_media** p_med) for (i=0; i<count; i++) { codec = media->get_media_codec_list() [i]; - tmp = this->convert_int_to_string (codec->getPayload ()); + tmp = this->convert_int_to_string (codec->getPayloadType ()); _debug ("%s", tmp.c_str()); pj_strdup2 (_pool, &med->desc.fmt[i], tmp.c_str()); @@ -108,20 +108,16 @@ void Sdp::set_media_descriptor_line (sdpMedia *media, pjmedia_sdp_media** p_med) // are entirely defined in the RFC 3351, but if we want to add other attributes like an asymmetric // connection, the rtpmap attribute will be useful to specify for which codec it is applicable rtpmap.pt = med->desc.fmt[i]; - rtpmap.enc_name = pj_str ( (char*) codec->getCodecName().c_str()); + rtpmap.enc_name = pj_str ( (char*) codec->getMimeSubtype().c_str()); // G722 require G722/8000 media description even if it is 16000 codec - if (codec->getPayload () == 9) { + if (codec->getPayloadType () == 9) { rtpmap.clock_rate = 8000; } else { rtpmap.clock_rate = codec->getClockRate(); } - // Add the channel number only if different from 1 - if (codec->getChannel() > 1) - rtpmap.param = pj_str ( (char*) codec->getChannel()); - else - rtpmap.param.slen = 0; + rtpmap.param.slen = 0; pjmedia_sdp_rtpmap_to_attr (_pool, &rtpmap, &attr); @@ -575,7 +571,7 @@ AudioCodec* Sdp::get_session_media (void) int nb_media; int nb_codec; - AudioCodec *codec = NULL; + sfl::Codec *codec = NULL; std::vector<sdpMedia*> media_list; _debug ("SDP: Get session media"); @@ -591,7 +587,7 @@ AudioCodec* Sdp::get_session_media (void) } } - return codec; + return static_cast<AudioCodec *>(codec); } diff --git a/sflphone-common/src/sip/sdpmedia.cpp b/sflphone-common/src/sip/sdpmedia.cpp index f35bdd5907c65a0f791a12f673f2067df16336ea..e1cdde423aa524b1bb779f8d7d0f5fa9d3c5841d 100644 --- a/sflphone-common/src/sip/sdpmedia.cpp +++ b/sflphone-common/src/sip/sdpmedia.cpp @@ -103,8 +103,7 @@ std::string sdpMedia::get_media_type_str (void) return value; } - -void sdpMedia::add_codec (AudioCodec* codec) +void sdpMedia::add_codec (sfl::Codec* codec) { _codec_list.push_back (codec); } @@ -115,16 +114,16 @@ void sdpMedia::remove_codec (std::string codecName) int i; int size; std::string enc_name; - std::vector<AudioCodec*>::iterator iter; + std::vector<sfl::Codec*>::iterator iter; size = _codec_list.size(); std::cout << "vector size: " << size << std::endl; for (i=0 ; i<size ; i++) { - std::cout << _codec_list[i]->getCodecName().c_str() << std::endl; + std::cout << _codec_list[i]->getMimeSubtype().c_str() << std::endl; - if (strcmp (_codec_list[i]->getCodecName().c_str(), codecName.c_str()) == 0) { - std::cout << "erase " <<_codec_list[i]->getCodecName() << std::endl; + if (strcmp (_codec_list[i]->getMimeSubtype().c_str(), codecName.c_str()) == 0) { + std::cout << "erase " <<_codec_list[i]->getMimeSubtype() << std::endl; iter = _codec_list.begin() +i; _codec_list.erase (iter); break; @@ -167,7 +166,7 @@ std::string sdpMedia::to_string (void) display << ":"; for (i=0; i<size; i++) { - display << _codec_list[i]->getCodecName() << "/"; + display << _codec_list[i]->getMimeSubtype() << "/"; } display << ":" << get_stream_direction_str() << std::endl; diff --git a/sflphone-common/src/sip/sdpmedia.h b/sflphone-common/src/sip/sdpmedia.h index 2a7e4a558b548929d6a3053d08297c41eb59ddcc..767f56077d3b71b60b285150e331643cea2ff1e1 100644 --- a/sflphone-common/src/sip/sdpmedia.h +++ b/sflphone-common/src/sip/sdpmedia.h @@ -90,7 +90,7 @@ class sdpMedia /* * Read accessor. Return the list of codecs */ - std::vector<AudioCodec*> get_media_codec_list() { + std::vector<sfl::Codec*> get_media_codec_list() { return _codec_list; } @@ -132,7 +132,7 @@ class sdpMedia * * @param payload The payload type */ - void add_codec (AudioCodec *codec); + void add_codec (sfl::Codec *codec); /* * Remove a codec from the current media codecs vector @@ -178,7 +178,7 @@ class sdpMedia mediaType _media_type; /* The media codec vector */ - std::vector< AudioCodec* > _codec_list; + std::vector< sfl::Codec* > _codec_list; /* the transport port */ int _port; diff --git a/sflphone-common/src/sip/sipvoiplink.cpp b/sflphone-common/src/sip/sipvoiplink.cpp index 01c2082ab6caa60aac62175f286a3ba9ea6eee33..eff8d19906affebf0d5e01b9a5ab910c630a208e 100644 --- a/sflphone-common/src/sip/sipvoiplink.cpp +++ b/sflphone-common/src/sip/sipvoiplink.cpp @@ -681,7 +681,7 @@ Call *SIPVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl) if (addrSdp == "0.0.0.0") loadSIPLocalIP (&addrSdp); - AudioCodec* audiocodec = Manager::instance().getCodecDescriptorMap().instantiateCodec (PAYLOAD_CODEC_ULAW); + sfl::Codec* audiocodec = Manager::instance().getCodecDescriptorMap().instantiateCodec (PAYLOAD_CODEC_ULAW); if (audiocodec == NULL) { _error ("UserAgent: Could not instantiate codec"); @@ -694,7 +694,7 @@ Call *SIPVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl) call->getAudioRtp()->initAudioRtpSession (call); call->getAudioRtp()->initLocalCryptoInfo (call); _info ("UserAgent: Start audio rtp session"); - call->getAudioRtp()->start (audiocodec); + call->getAudioRtp()->start (static_cast<AudioCodec *>(audiocodec)); } catch (...) { _error ("UserAgent: Error: Failed to create rtp thread from newOutGoingCall"); } @@ -1042,26 +1042,26 @@ SIPVoIPLink::offhold (const CallID& id) } // Retreive previously selected codec - AudioCodec *sessionMedia = call->getLocalSDP()->get_session_media(); + sfl::Codec *sessionMedia = call->getLocalSDP()->get_session_media(); if (!sessionMedia) return false; // Get PayloadType for this codec - AudioCodecType pl = (AudioCodecType) sessionMedia->getPayload(); + AudioCodecType pl = (AudioCodecType) sessionMedia->getPayloadType(); _debug ("UserAgent: Payload from session media %d", pl); try { // Create a new instance for this codec - AudioCodec* audiocodec = Manager::instance().getCodecDescriptorMap().instantiateCodec (pl); + sfl::Codec* audiocodec = Manager::instance().getCodecDescriptorMap().instantiateCodec (pl); if (audiocodec == NULL) _error ("UserAgent: No audiocodec found"); call->getAudioRtp()->initAudioRtpConfig (call); call->getAudioRtp()->initAudioRtpSession (call); - call->getAudioRtp()->start (audiocodec); + call->getAudioRtp()->start (static_cast<AudioCodec *>(audiocodec)); } catch (...) { _debug ("! SIP Failure: Unable to create RTP Session (%s:%d)", __FILE__, __LINE__); @@ -1328,7 +1328,7 @@ SIPVoIPLink::getCurrentCodecName() { SIPCall *call; - AudioCodec *ac = NULL; + sfl::Codec *ac = NULL; std::string name = ""; call = getSIPCall (Manager::instance().getCurrentCallId()); @@ -1337,7 +1337,7 @@ SIPVoIPLink::getCurrentCodecName() ac = call->getLocalSDP()->get_session_media(); if (ac) - name = ac->getCodecName(); + name = ac->getMimeSubtype(); return name; } @@ -1744,7 +1744,7 @@ bool SIPVoIPLink::SIPNewIpToIpCall (const CallID& id, const std::string& to) // call->getLocalSDP()->set_ip_address (addrSdp); // call->getLocalSDP()->create_initial_offer (account->getActiveCodecs ()); - AudioCodec* audiocodec = Manager::instance().getCodecDescriptorMap().instantiateCodec (PAYLOAD_CODEC_ULAW); + sfl::Codec* audiocodec = Manager::instance().getCodecDescriptorMap().instantiateCodec (PAYLOAD_CODEC_ULAW); // Audio Rtp Session must be initialized before creating initial offer in SDP session // since SDES require crypto attribute. @@ -1752,7 +1752,7 @@ bool SIPVoIPLink::SIPNewIpToIpCall (const CallID& id, const std::string& to) call->getAudioRtp()->initAudioRtpConfig (call); call->getAudioRtp()->initAudioRtpSession (call); call->getAudioRtp()->initLocalCryptoInfo (call); - call->getAudioRtp()->start (audiocodec); + call->getAudioRtp()->start (static_cast<AudioCodec *>(audiocodec)); } catch (...) { _debug ("UserAgent: Unable to create RTP Session in new IP2IP call (%s:%d)", __FILE__, __LINE__); } @@ -3376,7 +3376,7 @@ void sdp_media_update_cb (pjsip_inv_session *inv, pj_status_t status) if (!sessionMedia) return; - AudioCodecType pl = (AudioCodecType) sessionMedia->getPayload(); + AudioCodecType pl = (AudioCodecType) sessionMedia->getPayloadType(); try { call->setAudioStart (true); @@ -3384,12 +3384,12 @@ void sdp_media_update_cb (pjsip_inv_session *inv, pj_status_t status) // udate session media only if required if (pl != call->getAudioRtp()->getSessionMedia()) { - AudioCodec* audiocodec = Manager::instance().getCodecDescriptorMap().instantiateCodec (pl); + sfl::Codec* audiocodec = Manager::instance().getCodecDescriptorMap().instantiateCodec (pl); if (audiocodec == NULL) _error ("UserAgent: No audiocodec found"); - call->getAudioRtp()->updateSessionMedia (audiocodec); + call->getAudioRtp()->updateSessionMedia (static_cast<AudioCodec *>(audiocodec)); } } catch (exception& rtpException) { _error ("UserAgent: Error: %s", rtpException.what()); @@ -3893,12 +3893,12 @@ transaction_request_cb (pjsip_rx_data *rdata) status = call->getLocalSDP()->receiving_initial_offer (r_sdp, account->getActiveCodecs ()); - AudioCodec* audiocodec = Manager::instance().getCodecDescriptorMap().instantiateCodec (PAYLOAD_CODEC_ULAW); + sfl::Codec* audiocodec = Manager::instance().getCodecDescriptorMap().instantiateCodec (PAYLOAD_CODEC_ULAW); // Init audio rtp session try { _debug ("UserAgent: Create RTP session for this call"); - call->getAudioRtp()->start (audiocodec); + call->getAudioRtp()->start (static_cast<AudioCodec *>(audiocodec)); } catch (...) { _warn ("UserAgent: Error: Failed to create rtp thread from answer"); } diff --git a/sflphone-common/test/Makefile.am b/sflphone-common/test/Makefile.am index 0abd6c05a94e8ef1ad166908595855ccc4711be1..8803ff272ac63b5b1738f6241820c203aa9f54de 100644 --- a/sflphone-common/test/Makefile.am +++ b/sflphone-common/test/Makefile.am @@ -30,9 +30,11 @@ test_SOURCES = \ instantmessagingtest.h \ instantmessagingtest.cpp \ siptest.h \ - siptest.cpp - # sdptest.h \ - # sdptest.cpp + siptest.cpp \ + sdpsession.h \ + sdpsession.cpp \ + sdptest.h \ + sdptest.cpp LLIBS=$(CPPUNIT_LIBS) \ ../src/sflphoned-logger.o \