Skip to content

Commit

Permalink
Adding MP3 encoding using lame as an option
Browse files Browse the repository at this point in the history
  • Loading branch information
tachang committed Apr 22, 2021
1 parent d0da079 commit 59080a4
Show file tree
Hide file tree
Showing 15 changed files with 399 additions and 42 deletions.
16 changes: 13 additions & 3 deletions inc/ALSACapture.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,29 @@

#include <alsa/asoundlib.h>
#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<snd_pcm_format_t> & 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<snd_pcm_format_t> & 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;
std::list<snd_pcm_format_t> m_formatList;
unsigned int m_sampleRate;
unsigned int m_channels;
int m_verbose;
AudioCompressor* m_audioCompressor;
};

class ALSACapture : public DeviceInterface
Expand Down Expand Up @@ -61,6 +69,8 @@ class ALSACapture : public DeviceInterface
unsigned long m_periodSize;
ALSACaptureParameters m_params;
snd_pcm_format_t m_fmt;


};

#endif
Expand Down
22 changes: 22 additions & 0 deletions inc/AudioCompressor.h
Original file line number Diff line number Diff line change
@@ -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:
};
26 changes: 26 additions & 0 deletions inc/MP3AudioCompressor.h
Original file line number Diff line number Diff line change
@@ -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 <lame.h>
#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;
};
18 changes: 18 additions & 0 deletions inc/NullAudioCompressor.h
Original file line number Diff line number Diff line change
@@ -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:
};
16 changes: 14 additions & 2 deletions inc/ServerMediaSubsession.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,20 @@ class BaseServerMediaSubsession
{
public:
BaseServerMediaSubsession(StreamReplicator* replicator): m_replicator(replicator) {

V4L2DeviceSource* deviceSource = dynamic_cast<V4L2DeviceSource*>(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;
}


}

// -----------------------------------------
Expand All @@ -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) {
Expand Down Expand Up @@ -100,6 +108,8 @@ class BaseServerMediaSubsession
break;
}
os << "/" << sampleRate << "/" << channels;


#endif
return os.str();
}
Expand All @@ -111,6 +121,8 @@ class BaseServerMediaSubsession

protected:
StreamReplicator* m_replicator;
std::string m_format;
std::string m_format;
int m_compressedAudioFmt;

};

3 changes: 2 additions & 1 deletion inc/UnicastServerMediaSubsession.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 4 additions & 3 deletions inc/V4l2RTSPServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "MulticastServerMediaSubsession.h"
#include "TSServerMediaSubsession.h"
#include "HTTPServer.h"
#include "AudioCompressor.h"

class V4l2RTSPServer {
public:
Expand Down Expand Up @@ -124,13 +125,13 @@ class V4l2RTSPServer {
#ifdef HAVE_ALSA
StreamReplicator* CreateAudioReplicator(
const std::string& audioDev, const std::list<snd_pcm_format_t>& 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<ServerMediaSubsession*> subSession;
if (videoReplicator)
Expand All @@ -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);
}
Expand Down
39 changes: 36 additions & 3 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@

#include "DeviceSourceFactory.h"
#include "V4l2RTSPServer.h"
#include "AudioCompressor.h"
#include "NullAudioCompressor.h"
#include "MP3AudioCompressor.h"


// -----------------------------------------
Expand Down Expand Up @@ -156,6 +159,12 @@ int main(int argc, char** argv)
int audioNbChannels = 2;
std::list<snd_pcm_format_t> audioFmtList;
snd_pcm_format_t audioFmt = SND_PCM_FORMAT_UNKNOWN;
int compressedAudioFmt = COMPRESSED_AUDIO_FMT_NONE;

AudioCompressor *compressor;
std::list<AudioCompressor *> audioCompressors;


#endif
const char* defaultPort = getenv("PORT");
if (defaultPort != NULL) {
Expand All @@ -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)
{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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


Expand All @@ -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)
Expand Down
Loading

0 comments on commit 59080a4

Please sign in to comment.