From 59080a47ffab24f2384c3a8147d12bf3474b0367 Mon Sep 17 00:00:00 2001 From: Jeff Tchang Date: Mon, 19 Apr 2021 08:16:38 -0700 Subject: [PATCH] Adding MP3 encoding using lame as an option --- inc/ALSACapture.h | 16 +++- inc/AudioCompressor.h | 22 +++++ inc/MP3AudioCompressor.h | 26 ++++++ inc/NullAudioCompressor.h | 18 +++++ inc/ServerMediaSubsession.h | 16 +++- inc/UnicastServerMediaSubsession.h | 3 +- inc/V4l2RTSPServer.h | 7 +- main.cpp | 39 ++++++++- src/ALSACapture.cpp | 102 +++++++++++++++++------- src/AudioCompressor.cpp | 20 +++++ src/MP3AudioCompressor.cpp | 115 +++++++++++++++++++++++++++ src/NullAudioCompressor.cpp | 24 ++++++ src/ServerMediaSubsession.cpp | 10 +++ src/UnicastServerMediaSubsession.cpp | 19 ++++- src/V4l2RTSPServer.cpp | 4 +- 15 files changed, 399 insertions(+), 42 deletions(-) create mode 100644 inc/AudioCompressor.h create mode 100644 inc/MP3AudioCompressor.h create mode 100644 inc/NullAudioCompressor.h create mode 100644 src/AudioCompressor.cpp create mode 100644 src/MP3AudioCompressor.cpp create mode 100644 src/NullAudioCompressor.cpp diff --git a/inc/ALSACapture.h b/inc/ALSACapture.h index a314855..2c6b9ca 100755 --- a/inc/ALSACapture.h +++ b/inc/ALSACapture.h @@ -18,14 +18,21 @@ #include #include "logger.h" +#include "AudioCompressor.h" + + +#define COMPRESSED_AUDIO_FMT_NONE 0 +#define COMPRESSED_AUDIO_FMT_MP3 1 #include "DeviceInterface.h" struct ALSACaptureParameters { - ALSACaptureParameters(const char* devname, const std::list & formatList, unsigned int sampleRate, unsigned int channels, int verbose) : - m_devName(devname), m_formatList(formatList), m_sampleRate(sampleRate), m_channels(channels), m_verbose(verbose) { - + ALSACaptureParameters(const char* devname, const std::list & formatList, + unsigned int sampleRate, unsigned int channels, int verbose, AudioCompressor* audioCompressor) : + m_devName(devname), m_formatList(formatList), m_sampleRate(sampleRate), m_channels(channels), + m_verbose(verbose), m_audioCompressor(audioCompressor) { + } std::string m_devName; @@ -33,6 +40,7 @@ struct ALSACaptureParameters unsigned int m_sampleRate; unsigned int m_channels; int m_verbose; + AudioCompressor* m_audioCompressor; }; class ALSACapture : public DeviceInterface @@ -61,6 +69,8 @@ class ALSACapture : public DeviceInterface unsigned long m_periodSize; ALSACaptureParameters m_params; snd_pcm_format_t m_fmt; + + }; #endif diff --git a/inc/AudioCompressor.h b/inc/AudioCompressor.h new file mode 100644 index 0000000..ad0044c --- /dev/null +++ b/inc/AudioCompressor.h @@ -0,0 +1,22 @@ +/* --------------------------------------------------------------------------- +** This software is in the public domain, furnished "as is", without technical +** support, and with no warranty, express or implied, as to its usefulness for +** any purpose. +** +** AudioCompressor.h +** +** Contains abstract class for audio compressors +** +** -------------------------------------------------------------------------*/ + +#pragma once + +#include "logger.h" + +class AudioCompressor +{ + public: + AudioCompressor(); + virtual int compress(short* pcm_data, int sample_count, char* output_buffer, int output_buffer_size) { return -1; }; + private: +}; diff --git a/inc/MP3AudioCompressor.h b/inc/MP3AudioCompressor.h new file mode 100644 index 0000000..9b02420 --- /dev/null +++ b/inc/MP3AudioCompressor.h @@ -0,0 +1,26 @@ +/* --------------------------------------------------------------------------- +** This software is in the public domain, furnished "as is", without technical +** support, and with no warranty, express or implied, as to its usefulness for +** any purpose. +** +** MP3AudioCompressor.h +** +** Contains abstract class for audio compressors +** +** -------------------------------------------------------------------------*/ + +#pragma once + +#include "logger.h" +#include +#include "AudioCompressor.h" + +class MP3AudioCompressor: public AudioCompressor +{ + public: + MP3AudioCompressor(); + MP3AudioCompressor(int channels, int samplerate); + int compress(short* pcm_data, int sample_count, char* output_buffer, int output_buffer_size); + private: + lame_global_flags* gfp; +}; diff --git a/inc/NullAudioCompressor.h b/inc/NullAudioCompressor.h new file mode 100644 index 0000000..3ee349c --- /dev/null +++ b/inc/NullAudioCompressor.h @@ -0,0 +1,18 @@ +/* --------------------------------------------------------------------------- +** This software is in the public domain, furnished "as is", without technical +** support, and with no warranty, express or implied, as to its usefulness for +** any purpose. +** -------------------------------------------------------------------------*/ + +#pragma once + +#include "logger.h" +#include "AudioCompressor.h" + +class NullAudioCompressor: public AudioCompressor +{ + public: + NullAudioCompressor(); + int compress(short* pcm_data, int sample_count, char* output_buffer, int output_buffer_size); + private: +}; diff --git a/inc/ServerMediaSubsession.h b/inc/ServerMediaSubsession.h index 43b8bf6..babe111 100755 --- a/inc/ServerMediaSubsession.h +++ b/inc/ServerMediaSubsession.h @@ -36,16 +36,20 @@ class BaseServerMediaSubsession { public: BaseServerMediaSubsession(StreamReplicator* replicator): m_replicator(replicator) { + V4L2DeviceSource* deviceSource = dynamic_cast(replicator->inputSource()); + if (deviceSource) { DeviceInterface* device = deviceSource->getDevice(); if (device->getVideoFormat() >= 0) { m_format = BaseServerMediaSubsession::getVideoRtpFormat(device->getVideoFormat()); } else { - m_format = BaseServerMediaSubsession::getAudioRtpFormat(device->getAudioFormat(), device->getSampleRate(), device->getChannels()); + m_format = BaseServerMediaSubsession::getAudioRtpFormat(device->getAudioFormat(), device->getSampleRate(), device->getChannels()); } LOG(NOTICE) << "format:" << m_format; } + + } // ----------------------------------------- @@ -69,9 +73,13 @@ class BaseServerMediaSubsession return rtpFormat; } + /* + * Return the format for the audio part of the RTP session. + */ static std::string getAudioRtpFormat(int format, int sampleRate, int channels) { std::ostringstream os; + #ifdef HAVE_ALSA os << "audio/"; switch (format) { @@ -100,6 +108,8 @@ class BaseServerMediaSubsession break; } os << "/" << sampleRate << "/" << channels; + + #endif return os.str(); } @@ -111,6 +121,8 @@ class BaseServerMediaSubsession protected: StreamReplicator* m_replicator; - std::string m_format; + std::string m_format; + int m_compressedAudioFmt; + }; diff --git a/inc/UnicastServerMediaSubsession.h b/inc/UnicastServerMediaSubsession.h index 6a343a5..bfa699a 100644 --- a/inc/UnicastServerMediaSubsession.h +++ b/inc/UnicastServerMediaSubsession.h @@ -18,11 +18,12 @@ class UnicastServerMediaSubsession : public OnDemandServerMediaSubsession , publ { public: static UnicastServerMediaSubsession* createNew(UsageEnvironment& env, StreamReplicator* replicator); + static UnicastServerMediaSubsession* createNew(UsageEnvironment& env, StreamReplicator* replicator, int compressedAudioFmt); protected: UnicastServerMediaSubsession(UsageEnvironment& env, StreamReplicator* replicator) : OnDemandServerMediaSubsession(env, False), BaseServerMediaSubsession(replicator) {} - + virtual FramedSource* createNewStreamSource(unsigned clientSessionId, unsigned& estBitrate); virtual RTPSink* createNewRTPSink(Groupsock* rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource* inputSource); virtual char const* getAuxSDPLine(RTPSink* rtpSink,FramedSource* inputSource); diff --git a/inc/V4l2RTSPServer.h b/inc/V4l2RTSPServer.h index f0843df..4ba78eb 100644 --- a/inc/V4l2RTSPServer.h +++ b/inc/V4l2RTSPServer.h @@ -22,6 +22,7 @@ #include "MulticastServerMediaSubsession.h" #include "TSServerMediaSubsession.h" #include "HTTPServer.h" +#include "AudioCompressor.h" class V4l2RTSPServer { public: @@ -124,13 +125,13 @@ class V4l2RTSPServer { #ifdef HAVE_ALSA StreamReplicator* CreateAudioReplicator( const std::string& audioDev, const std::list& audioFmtList, int audioFreq, int audioNbChannels, int verbose, - int queueSize, int useThread); + int queueSize, int useThread, AudioCompressor* compressor); #endif // ----------------------------------------- // Add unicast Session // ----------------------------------------- - int AddUnicastSession(const std::string& url, StreamReplicator* videoReplicator, StreamReplicator* audioReplicator) { + int AddUnicastSession(const std::string& url, StreamReplicator* videoReplicator, StreamReplicator* audioReplicator, int compressedAudioFmt) { // Create Unicast Session std::list subSession; if (videoReplicator) @@ -139,7 +140,7 @@ class V4l2RTSPServer { } if (audioReplicator) { - subSession.push_back(UnicastServerMediaSubsession::createNew(*this->env(), audioReplicator)); + subSession.push_back(UnicastServerMediaSubsession::createNew(*this->env(), audioReplicator, compressedAudioFmt)); } return this->addSession(url, subSession); } diff --git a/main.cpp b/main.cpp index bebe745..ba9c710 100755 --- a/main.cpp +++ b/main.cpp @@ -33,6 +33,9 @@ #include "DeviceSourceFactory.h" #include "V4l2RTSPServer.h" +#include "AudioCompressor.h" +#include "NullAudioCompressor.h" +#include "MP3AudioCompressor.h" // ----------------------------------------- @@ -156,6 +159,12 @@ int main(int argc, char** argv) int audioNbChannels = 2; std::list audioFmtList; snd_pcm_format_t audioFmt = SND_PCM_FORMAT_UNKNOWN; + int compressedAudioFmt = COMPRESSED_AUDIO_FMT_NONE; + + AudioCompressor *compressor; + std::list audioCompressors; + + #endif const char* defaultPort = getenv("PORT"); if (defaultPort != NULL) { @@ -164,7 +173,7 @@ int main(int argc, char** argv) // decode parameters int c = 0; - while ((c = getopt (argc, argv, "v::Q:O:b:" "I:P:p:m::u:M:ct:S::" "R:U:" "rwBsf::F:W:H:G:" "A:C:a:" "Vh")) != -1) + while ((c = getopt (argc, argv, "v::Q:O:b:" "I:P:p:m::u:M:ct:S::" "R:U:" "rwBsf::F:W:H:G:" "A:C:a:l:" "Vh")) != -1) { switch (c) { @@ -204,6 +213,10 @@ int main(int argc, char** argv) case 'A': audioFreq = atoi(optarg); break; case 'C': audioNbChannels = atoi(optarg); break; case 'a': audioFmt = decodeAudioFormat(optarg); if (audioFmt != SND_PCM_FORMAT_UNKNOWN) {audioFmtList.push_back(audioFmt);} ; break; + + case 'l': compressedAudioFmt = atoi(optarg); break; + + #endif // version @@ -255,6 +268,8 @@ int main(int argc, char** argv) std::cout << "\t -A freq : ALSA capture frequency and channel (default " << audioFreq << ")" << std::endl; std::cout << "\t -C channels : ALSA capture channels (default " << audioNbChannels << ")" << std::endl; std::cout << "\t -a fmt : ALSA capture audio format (default S16_BE)" << std::endl; + std::cout << "\t -l [number] : Compresssed audio format: 0 - None, 1 - MP3" << std::endl; + #endif std::cout << "\t Devices :" << std::endl; @@ -342,9 +357,26 @@ int main(int argc, char** argv) // Init Audio Capture StreamReplicator* audioReplicator = NULL; #ifdef HAVE_ALSA + + + + if (compressedAudioFmt == COMPRESSED_AUDIO_FMT_NONE) { + compressor = new NullAudioCompressor(); + audioCompressors.push_back(compressor); + } + + if (compressedAudioFmt == COMPRESSED_AUDIO_FMT_MP3) { + compressor = new MP3AudioCompressor(audioNbChannels, audioFreq); + audioCompressors.push_back(compressor); + } + + LOG(NOTICE) << "Using AudioCompressor: " << compressor; + + audioReplicator = rtspServer.CreateAudioReplicator( audioDev, audioFmtList, audioFreq, audioNbChannels, verbose, - queueSize, useThread); + queueSize, useThread, compressor); + #endif @@ -361,7 +393,8 @@ int main(int argc, char** argv) } // Create Unicast Session - nbSource += rtspServer.AddUnicastSession(baseUrl+url, videoReplicator, audioReplicator); + nbSource += rtspServer.AddUnicastSession(baseUrl+url, videoReplicator, audioReplicator, compressedAudioFmt); + } if (nbSource>0) diff --git a/src/ALSACapture.cpp b/src/ALSACapture.cpp index ac5f3a7..803609d 100644 --- a/src/ALSACapture.cpp +++ b/src/ALSACapture.cpp @@ -14,10 +14,12 @@ #ifdef HAVE_ALSA #include "ALSACapture.h" - +#include "NullAudioCompressor.h" ALSACapture* ALSACapture::createNew(const ALSACaptureParameters & params) { + LOG(NOTICE) << "params.m_audioCompressor: " << params.m_audioCompressor; + ALSACapture* capture = new ALSACapture(params); if (capture) { @@ -43,7 +45,10 @@ void ALSACapture::close() m_pcm = NULL; } } - + + + + ALSACapture::ALSACapture(const ALSACaptureParameters & params) : m_pcm(NULL), m_bufferSize(0), m_periodSize(0), m_params(params) { LOG(NOTICE) << "Open ALSA device: \"" << params.m_devName << "\""; @@ -102,8 +107,18 @@ ALSACapture::ALSACapture(const ALSACaptureParameters & params) : m_pcm(NULL), m_ } LOG(NOTICE) << "ALSA device: \"" << m_params.m_devName << "\" buffer_size:" << m_bufferSize << " period_size:" << m_periodSize << " rate:" << m_params.m_sampleRate; + + + // m_params.m_audioCompressor->init( + // m_params.m_channels, + // m_params.m_sampleRate + // ); + } - + +/* + * Attempts to set the ALSA hardware device to the format specified. + */ int ALSACapture::configureFormat(snd_pcm_hw_params_t *hw_params) { // try to set format, widht, height @@ -116,8 +131,9 @@ int ALSACapture::configureFormat(snd_pcm_hw_params_t *hw_params) { } else { LOG(NOTICE) << "set sample format device: " << m_params.m_devName << " to:" << format << " ok"; m_fmt = format; + // m_fmt = SND_PCM_FORMAT_MPEG; return 0; - } + } } return -1; } @@ -126,34 +142,66 @@ size_t ALSACapture::read(char* buffer, size_t bufferSize) { size_t size = 0; int fmt_phys_width_bytes = 0; - if (m_pcm != 0) - { - int fmt_phys_width_bits = snd_pcm_format_physical_width(m_fmt); - fmt_phys_width_bytes = fmt_phys_width_bits / 8; - - snd_pcm_sframes_t ret = snd_pcm_readi (m_pcm, buffer, m_periodSize*fmt_phys_width_bytes); - LOG(DEBUG) << "ALSA buffer in_size:" << m_periodSize*fmt_phys_width_bytes << " read_size:" << ret; - if (ret > 0) { - size = ret; - - // swap if capture in not in network order - if (!snd_pcm_format_big_endian(m_fmt)) { - for(unsigned int i = 0; i < size; i++){ - char * ptr = &buffer[i * fmt_phys_width_bytes * m_params.m_channels]; - - for(unsigned int j = 0; j < m_params.m_channels; j++){ - ptr += j * fmt_phys_width_bytes; - for (int k = 0; k < fmt_phys_width_bytes/2; k++) { - char byte = ptr[k]; - ptr[k] = ptr[fmt_phys_width_bytes - 1 - k]; - ptr[fmt_phys_width_bytes - 1 - k] = byte; - } + + // Worst case estimate of how big the MP3 encoded size will be + // Based on http://www.mit.edu/afs.new/sipb/user/golem/tmp/lame3.70/API + int mp3buf_size = 1.25 * m_periodSize + 7200; + int bytescopied = 0; + + char encoded_mp3_data[mp3buf_size]; + + // If there is no ALSA capture device for some reason just return 0 bytes read + if (m_pcm == 0) { + return 0; + } + + int fmt_phys_width_bits = snd_pcm_format_physical_width(m_fmt); + fmt_phys_width_bytes = fmt_phys_width_bits / 8; + + snd_pcm_sframes_t num_pcm_frames = snd_pcm_readi (m_pcm, buffer, m_periodSize*fmt_phys_width_bytes); + LOG(DEBUG) << "ALSA buffer in_size:" << m_periodSize*fmt_phys_width_bytes << " read_size:" << num_pcm_frames; + + if (num_pcm_frames <= 0) { + return 0; + } + + size = num_pcm_frames; + + + if (m_params.m_audioCompressor != NULL) { + // LOG(NOTICE) << "m_params.m_audioCompressor: " << m_params.m_audioCompressor; + bytescopied = m_params.m_audioCompressor->compress( + (short *)buffer, + num_pcm_frames, + (char *)encoded_mp3_data, + mp3buf_size + ); + + memcpy(buffer, encoded_mp3_data, bytescopied); + return bytescopied; + } + else { + + // swap if capture in not in network order + if (!snd_pcm_format_big_endian(m_fmt)) { + for(unsigned int i = 0; i < size; i++){ + char * ptr = &buffer[i * fmt_phys_width_bytes * m_params.m_channels]; + + for(unsigned int j = 0; j < m_params.m_channels; j++){ + ptr += j * fmt_phys_width_bytes; + for (int k = 0; k < fmt_phys_width_bytes/2; k++) { + char byte = ptr[k]; + ptr[k] = ptr[fmt_phys_width_bytes - 1 - k]; + ptr[fmt_phys_width_bytes - 1 - k] = byte; } } } } + return size * m_params.m_channels * fmt_phys_width_bytes; + } - return size * m_params.m_channels * fmt_phys_width_bytes; + + return 0; } int ALSACapture::getFd() diff --git a/src/AudioCompressor.cpp b/src/AudioCompressor.cpp new file mode 100644 index 0000000..cbf927b --- /dev/null +++ b/src/AudioCompressor.cpp @@ -0,0 +1,20 @@ +/* --------------------------------------------------------------------------- +** This software is in the public domain, furnished "as is", without technical +** support, and with no warranty, express or implied, as to its usefulness for +** any purpose. +** +** +** -------------------------------------------------------------------------*/ + +#ifdef HAVE_ALSA + +#include "AudioCompressor.h" + + +AudioCompressor::AudioCompressor(void) +{ + LOG(NOTICE) << "Initializing AudioCompressor"; +} + +#endif + diff --git a/src/MP3AudioCompressor.cpp b/src/MP3AudioCompressor.cpp new file mode 100644 index 0000000..657fd93 --- /dev/null +++ b/src/MP3AudioCompressor.cpp @@ -0,0 +1,115 @@ +/* --------------------------------------------------------------------------- +** This software is in the public domain, furnished "as is", without technical +** support, and with no warranty, express or implied, as to its usefulness for +** any purpose. +** +** +** -------------------------------------------------------------------------*/ + +#ifdef HAVE_ALSA + +#include "MP3AudioCompressor.h" + + + +/** + * lame_error_callback, lame_message_callback, lame_debug_callback: LAME + * logging callback functions. + * + * [Parameters] + * format: Format string. + * args: Format arguments. + */ + +static void lame_error_callback(const char *format, va_list args) +{ + char buff[512]; + vsnprintf(buff, sizeof(buff), format, args); + LOG(ERROR) << buff; +} + +static void lame_message_callback(const char *format, va_list args) +{ + char buff[512]; + vsnprintf(buff, sizeof(buff), format, args); + LOG(NOTICE) << buff; +} + +MP3AudioCompressor::MP3AudioCompressor(void) +{ + int err; + + LOG(NOTICE) << "Initializing MP3AudioCompressor"; + + // Lame Init + gfp = lame_init(); + + lame_set_errorf(gfp, lame_error_callback); + lame_set_msgf(gfp, lame_message_callback); + //lame_set_debugf(lame, lame_debug_callback); + lame_set_num_channels(gfp, 1); + //lame_set_mode(gfp, 3); + lame_set_in_samplerate(gfp, 48000); + lame_set_out_samplerate(gfp, 48000); + // lame_set_scale(gfp, 3.0); + err = lame_init_params(gfp); + + if (err < 0) { + LOG(ERROR) << "Error initializing Lame encoder"; + } + lame_print_config(gfp); +} + +MP3AudioCompressor::MP3AudioCompressor(int channels, int samplerate) +{ + int err; + + LOG(NOTICE) << "Initializing MP3AudioCompressor"; + + // Lame Init + gfp = lame_init(); + + lame_set_errorf(gfp, lame_error_callback); + lame_set_msgf(gfp, lame_message_callback); + //lame_set_debugf(lame, lame_debug_callback); + lame_set_num_channels(gfp, channels); + //lame_set_mode(gfp, 3); + lame_set_in_samplerate(gfp, samplerate); + lame_set_out_samplerate(gfp, samplerate); + // lame_set_scale(gfp, 3.0); + err = lame_init_params(gfp); + + if (err < 0) { + LOG(ERROR) << "Error initializing Lame encoder"; + } + lame_print_config(gfp); +} + + +int MP3AudioCompressor::compress(short* pcm_data, int sample_count, char* output_buffer, int output_buffer_size) +{ + int bytescopied = 0; + + + // Encode the buffer. Even though we use snd_pcm_readi + // for interleaved frames when there is only one channel you + // just get an array of data that has no interleaved. + bytescopied = lame_encode_buffer( + gfp, + (short int *)pcm_data, // Left raw PCM data + NULL, // Right raw PCM data + sample_count, // Sample count + (unsigned char*)output_buffer, // Output buffer + output_buffer_size // Outbut buffer size + ); + + LOG(DEBUG) << "Encoded " << bytescopied << " bytes to mp3"; + + return bytescopied; + +} + + + +#endif + diff --git a/src/NullAudioCompressor.cpp b/src/NullAudioCompressor.cpp new file mode 100644 index 0000000..2d422cd --- /dev/null +++ b/src/NullAudioCompressor.cpp @@ -0,0 +1,24 @@ +/* --------------------------------------------------------------------------- +** This software is in the public domain, furnished "as is", without technical +** support, and with no warranty, express or implied, as to its usefulness for +** any purpose. +** +** +** -------------------------------------------------------------------------*/ + +#ifdef HAVE_ALSA + +#include "NullAudioCompressor.h" + + +NullAudioCompressor::NullAudioCompressor(void) +{ + LOG(NOTICE) << "Initializing NullAudioCompressor"; +} + +int NullAudioCompressor::compress(short* pcm_data, int sample_count, char* output_buffer, int output_buffer_size) +{ + return 0; +} + +#endif diff --git a/src/ServerMediaSubsession.cpp b/src/ServerMediaSubsession.cpp index 5d31828..af3c1ec 100755 --- a/src/ServerMediaSubsession.cpp +++ b/src/ServerMediaSubsession.cpp @@ -49,6 +49,8 @@ FramedSource* BaseServerMediaSubsession::createSource(UsageEnvironment& env, Fra RTPSink* BaseServerMediaSubsession::createSink(UsageEnvironment& env, Groupsock* rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, const std::string& format, V4L2DeviceSource* source) { RTPSink* videoSink = NULL; + + if (format == "video/MP2T") { videoSink = SimpleRTPSink::createNew(env, rtpGroupsock,rtpPayloadTypeIfDynamic, 90000, "video", "MP2T", 1, True, False); @@ -99,6 +101,14 @@ RTPSink* BaseServerMediaSubsession::createSink(UsageEnvironment& env, Groupsock std::string channels("2"); getline(is, channels); videoSink = SimpleRTPSink::createNew(env, rtpGroupsock,rtpPayloadTypeIfDynamic, atoi(sampleRate.c_str()), "audio", "L16", atoi(channels.c_str()), True, False); + } + else if (format.find("audio/MPEG") == 0) + { + videoSink = MPEG1or2AudioRTPSink::createNew(env, rtpGroupsock); + } + else + { + LOG(ERROR) << "Unable to create sink due to unknown format: " << format; } return videoSink; } diff --git a/src/UnicastServerMediaSubsession.cpp b/src/UnicastServerMediaSubsession.cpp index f56ff05..15b696e 100755 --- a/src/UnicastServerMediaSubsession.cpp +++ b/src/UnicastServerMediaSubsession.cpp @@ -18,7 +18,24 @@ UnicastServerMediaSubsession* UnicastServerMediaSubsession::createNew(UsageEnvir { return new UnicastServerMediaSubsession(env,replicator); } - + +UnicastServerMediaSubsession* UnicastServerMediaSubsession::createNew(UsageEnvironment& env, StreamReplicator* replicator, int compressedAudioFmt) +{ + UnicastServerMediaSubsession* s = new UnicastServerMediaSubsession(env,replicator); + + // If compression is enabled we need to assign the proper RTP format for the audio + switch(compressedAudioFmt) { + case COMPRESSED_AUDIO_FMT_NONE: + break; + case COMPRESSED_AUDIO_FMT_MP3: + s->m_format.assign("audio/MPEG"); + break; + } + + LOG(NOTICE) << "Compressed audio format:" << s->m_format; + return s; +} + FramedSource* UnicastServerMediaSubsession::createNewStreamSource(unsigned clientSessionId, unsigned& estBitrate) { estBitrate = 500; diff --git a/src/V4l2RTSPServer.cpp b/src/V4l2RTSPServer.cpp index ba99858..fca76dc 100644 --- a/src/V4l2RTSPServer.cpp +++ b/src/V4l2RTSPServer.cpp @@ -172,7 +172,7 @@ std::string getV4l2Alsa(const std::string& v4l2device) { StreamReplicator* V4l2RTSPServer::CreateAudioReplicator( const std::string& audioDev, const std::list& audioFmtList, int audioFreq, int audioNbChannels, int verbose, - int queueSize, int useThread) { + int queueSize, int useThread, AudioCompressor* audioCompressor) { StreamReplicator* audioReplicator = NULL; if (!audioDev.empty()) { @@ -182,7 +182,7 @@ StreamReplicator* V4l2RTSPServer::CreateAudioReplicator( // Init audio capture LOG(NOTICE) << "Create ALSA Source..." << audioDevice; - ALSACaptureParameters param(audioDevice.c_str(), audioFmtList, audioFreq, audioNbChannels, verbose); + ALSACaptureParameters param(audioDevice.c_str(), audioFmtList, audioFreq, audioNbChannels, verbose, audioCompressor); ALSACapture* audioCapture = ALSACapture::createNew(param); if (audioCapture) {