Add namespace for encoder and decoder

This commit is contained in:
badaix 2019-11-04 14:53:02 +01:00
parent c1a2fedd8d
commit 07e8290ee4
25 changed files with 124 additions and 38 deletions

View file

@ -104,18 +104,18 @@ void Controller::onMessageReceived(ClientConnection* /*connection*/, const msg::
player_.reset(nullptr); player_.reset(nullptr);
if (headerChunk_->codec == "pcm") if (headerChunk_->codec == "pcm")
decoder_.reset(new PcmDecoder()); decoder_ = make_unique<decoder::PcmDecoder>();
#if defined(HAS_OGG) && (defined(HAS_TREMOR) || defined(HAS_VORBIS)) #if defined(HAS_OGG) && (defined(HAS_TREMOR) || defined(HAS_VORBIS))
else if (headerChunk_->codec == "ogg") else if (headerChunk_->codec == "ogg")
decoder_.reset(new OggDecoder()); decoder_ = make_unique<decoder::OggDecoder>();
#endif #endif
#if defined(HAS_FLAC) #if defined(HAS_FLAC)
else if (headerChunk_->codec == "flac") else if (headerChunk_->codec == "flac")
decoder_.reset(new FlacDecoder()); decoder_ = make_unique<decoder::FlacDecoder>();
#endif #endif
#if defined(HAS_OPUS) #if defined(HAS_OPUS)
else if (headerChunk_->codec == "opus") else if (headerChunk_->codec == "opus")
decoder_.reset(new OpusDecoder()); decoder_ = make_unique<decoder::OpusDecoder>();
#endif #endif
else else
throw SnapException("codec not supported: \"" + headerChunk_->codec + "\""); throw SnapException("codec not supported: \"" + headerChunk_->codec + "\"");
@ -127,11 +127,11 @@ void Controller::onMessageReceived(ClientConnection* /*connection*/, const msg::
stream_->setBufferLen(serverSettings_->getBufferMs() - latency_); stream_->setBufferLen(serverSettings_->getBufferMs() - latency_);
#ifdef HAS_ALSA #ifdef HAS_ALSA
player_.reset(new AlsaPlayer(pcmDevice_, stream_)); player_ = make_unique<AlsaPlayer>(pcmDevice_, stream_);
#elif HAS_OPENSL #elif HAS_OPENSL
player_.reset(new OpenslPlayer(pcmDevice_, stream_)); player_ = make_unique<OpenslPlayer>(pcmDevice_, stream_);
#elif HAS_COREAUDIO #elif HAS_COREAUDIO
player_.reset(new CoreAudioPlayer(pcmDevice_, stream_)); player_ = make_unique<CoreAudioPlayer>(pcmDevice_, stream_);
#else #else
throw SnapException("No audio player support"); throw SnapException("No audio player support");
#endif #endif

View file

@ -73,7 +73,7 @@ private:
int latency_; int latency_;
std::unique_ptr<ClientConnection> clientConnection_; std::unique_ptr<ClientConnection> clientConnection_;
std::shared_ptr<Stream> stream_; std::shared_ptr<Stream> stream_;
std::unique_ptr<Decoder> decoder_; std::unique_ptr<decoder::Decoder> decoder_;
std::unique_ptr<Player> player_; std::unique_ptr<Player> player_;
std::shared_ptr<MetadataAdapter> meta_; std::shared_ptr<MetadataAdapter> meta_;
std::shared_ptr<msg::ServerSettings> serverSettings_; std::shared_ptr<msg::ServerSettings> serverSettings_;

View file

@ -23,6 +23,8 @@
#include "message/pcm_chunk.hpp" #include "message/pcm_chunk.hpp"
#include <mutex> #include <mutex>
namespace decoder
{
class Decoder class Decoder
{ {
@ -37,5 +39,6 @@ protected:
std::mutex mutex_; std::mutex mutex_;
}; };
} // namespace decoder
#endif #endif

View file

@ -27,20 +27,26 @@
using namespace std; using namespace std;
namespace decoder
{
static FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder* decoder, FLAC__byte buffer[], size_t* bytes, void* client_data); namespace callback
static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder* decoder, const FLAC__Frame* frame, const FLAC__int32* const buffer[], {
void* client_data); FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder* decoder, FLAC__byte buffer[], size_t* bytes, void* client_data);
static void metadata_callback(const FLAC__StreamDecoder* decoder, const FLAC__StreamMetadata* metadata, void* client_data); FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder* decoder, const FLAC__Frame* frame, const FLAC__int32* const buffer[],
static void error_callback(const FLAC__StreamDecoder* decoder, FLAC__StreamDecoderErrorStatus status, void* client_data); void* client_data);
void metadata_callback(const FLAC__StreamDecoder* decoder, const FLAC__StreamMetadata* metadata, void* client_data);
void error_callback(const FLAC__StreamDecoder* decoder, FLAC__StreamDecoderErrorStatus status, void* client_data);
static msg::CodecHeader* flacHeader = nullptr; } // namespace callback
static msg::PcmChunk* flacChunk = nullptr;
static msg::PcmChunk* pcmChunk = nullptr;
static SampleFormat sampleFormat;
static FLAC__StreamDecoder* decoder = nullptr;
namespace
{
msg::CodecHeader* flacHeader = nullptr;
msg::PcmChunk* flacChunk = nullptr;
msg::PcmChunk* pcmChunk = nullptr;
SampleFormat sampleFormat;
FLAC__StreamDecoder* decoder = nullptr;
} // namespace
FlacDecoder::FlacDecoder() : Decoder(), lastError_(nullptr) FlacDecoder::FlacDecoder() : Decoder(), lastError_(nullptr)
@ -105,8 +111,8 @@ SampleFormat FlacDecoder::setHeader(msg::CodecHeader* chunk)
throw SnapException("ERROR: allocating decoder"); throw SnapException("ERROR: allocating decoder");
// (void)FLAC__stream_decoder_set_md5_checking(decoder, true); // (void)FLAC__stream_decoder_set_md5_checking(decoder, true);
init_status = init_status = FLAC__stream_decoder_init_stream(decoder, callback::read_callback, nullptr, nullptr, nullptr, nullptr, callback::write_callback,
FLAC__stream_decoder_init_stream(decoder, read_callback, nullptr, nullptr, nullptr, nullptr, write_callback, metadata_callback, error_callback, this); callback::metadata_callback, callback::error_callback, this);
if (init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) if (init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK)
throw SnapException("ERROR: initializing decoder: " + string(FLAC__StreamDecoderInitStatusString[init_status])); throw SnapException("ERROR: initializing decoder: " + string(FLAC__StreamDecoderInitStatusString[init_status]));
@ -118,7 +124,8 @@ SampleFormat FlacDecoder::setHeader(msg::CodecHeader* chunk)
return sampleFormat; return sampleFormat;
} }
namespace callback
{
FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder* /*decoder*/, FLAC__byte buffer[], size_t* bytes, void* client_data) FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder* /*decoder*/, FLAC__byte buffer[], size_t* bytes, void* client_data)
{ {
if (flacHeader != nullptr) if (flacHeader != nullptr)
@ -213,3 +220,6 @@ void error_callback(const FLAC__StreamDecoder* decoder, FLAC__StreamDecoderError
SLOG(ERROR) << "Got error callback: " << FLAC__StreamDecoderErrorStatusString[status] << "\n"; SLOG(ERROR) << "Got error callback: " << FLAC__StreamDecoderErrorStatusString[status] << "\n";
static_cast<FlacDecoder*>(client_data)->lastError_ = std::unique_ptr<FLAC__StreamDecoderErrorStatus>(new FLAC__StreamDecoderErrorStatus(status)); static_cast<FlacDecoder*>(client_data)->lastError_ = std::unique_ptr<FLAC__StreamDecoderErrorStatus>(new FLAC__StreamDecoderErrorStatus(status));
} }
} // namespace callback
} // namespace decoder

View file

@ -25,7 +25,8 @@
#include <atomic> #include <atomic>
#include <memory> #include <memory>
namespace decoder
{
struct CacheInfo struct CacheInfo
{ {
@ -58,5 +59,6 @@ public:
std::unique_ptr<FLAC__StreamDecoderErrorStatus> lastError_; std::unique_ptr<FLAC__StreamDecoderErrorStatus> lastError_;
}; };
} // namespace decoder
#endif #endif

View file

@ -28,6 +28,8 @@
using namespace std; using namespace std;
namespace decoder
{
OggDecoder::OggDecoder() : Decoder() OggDecoder::OggDecoder() : Decoder()
{ {
@ -238,3 +240,5 @@ SampleFormat OggDecoder::setHeader(msg::CodecHeader* chunk)
return sampleFormat_; return sampleFormat_;
} }
} // namespace decoder

View file

@ -26,6 +26,9 @@
#endif #endif
#include <ogg/ogg.h> #include <ogg/ogg.h>
namespace decoder
{
class OggDecoder : public Decoder class OggDecoder : public Decoder
{ {
public: public:
@ -59,5 +62,6 @@ private:
SampleFormat sampleFormat_; SampleFormat sampleFormat_;
}; };
} // namespace decoder
#endif #endif

View file

@ -21,6 +21,9 @@
#include "common/snap_exception.hpp" #include "common/snap_exception.hpp"
#include "common/str_compat.hpp" #include "common/str_compat.hpp"
namespace decoder
{
#define ID_OPUS 0x4F505553 #define ID_OPUS 0x4F505553
/// int: Number of samples per channel in the input signal. /// int: Number of samples per channel in the input signal.
@ -108,3 +111,5 @@ SampleFormat OpusDecoder::setHeader(msg::CodecHeader* chunk)
return sample_format_; return sample_format_;
} }
} // namespace decoder

View file

@ -21,6 +21,8 @@
#include "decoder/decoder.hpp" #include "decoder/decoder.hpp"
#include <opus/opus.h> #include <opus/opus.h>
namespace decoder
{
class OpusDecoder : public Decoder class OpusDecoder : public Decoder
{ {
@ -31,7 +33,9 @@ public:
SampleFormat setHeader(msg::CodecHeader* chunk) override; SampleFormat setHeader(msg::CodecHeader* chunk) override;
private: private:
OpusDecoder* dec_; ::OpusDecoder* dec_;
std::vector<opus_int16> pcm_; std::vector<opus_int16> pcm_;
SampleFormat sample_format_; SampleFormat sample_format_;
}; };
} // namespace decoder

View file

@ -21,6 +21,8 @@
#include "common/endian.hpp" #include "common/endian.hpp"
#include "common/snap_exception.hpp" #include "common/snap_exception.hpp"
namespace decoder
{
#define ID_RIFF 0x46464952 #define ID_RIFF 0x46464952
#define ID_WAVE 0x45564157 #define ID_WAVE 0x45564157
@ -118,3 +120,5 @@ SampleFormat PcmDecoder::setHeader(msg::CodecHeader* chunk)
return sampleFormat; return sampleFormat;
} }
} // namespace decoder

View file

@ -21,6 +21,9 @@
#include "decoder.hpp" #include "decoder.hpp"
namespace decoder
{
class PcmDecoder : public Decoder class PcmDecoder : public Decoder
{ {
public: public:
@ -29,5 +32,6 @@ public:
SampleFormat setHeader(msg::CodecHeader* chunk) override; SampleFormat setHeader(msg::CodecHeader* chunk) override;
}; };
} // namespace decoder
#endif #endif

View file

@ -26,6 +26,8 @@
#include "message/codec_header.hpp" #include "message/codec_header.hpp"
#include "message/pcm_chunk.hpp" #include "message/pcm_chunk.hpp"
namespace encoder
{
class Encoder; class Encoder;
@ -96,5 +98,6 @@ protected:
std::string codecOptions_; std::string codecOptions_;
}; };
} // namespace encoder
#endif #endif

View file

@ -34,6 +34,8 @@
using namespace std; using namespace std;
namespace encoder
{
Encoder* EncoderFactory::createEncoder(const std::string& codecSettings) const Encoder* EncoderFactory::createEncoder(const std::string& codecSettings) const
{ {
@ -76,3 +78,5 @@ Encoder* EncoderFactory::createEncoder(const std::string& codecSettings) const
} }
*/ */
} }
} // namespace encoder

View file

@ -4,6 +4,9 @@
#include "encoder.hpp" #include "encoder.hpp"
#include <string> #include <string>
namespace encoder
{
class EncoderFactory class EncoderFactory
{ {
public: public:
@ -11,5 +14,6 @@ public:
Encoder* createEncoder(const std::string& codecSettings) const; Encoder* createEncoder(const std::string& codecSettings) const;
}; };
} // namespace encoder
#endif #endif

View file

@ -25,6 +25,8 @@
using namespace std; using namespace std;
namespace encoder
{
FlacEncoder::FlacEncoder(const std::string& codecOptions) : Encoder(codecOptions), encoder_(nullptr), pcmBufferSize_(0), encodedSamples_(0) FlacEncoder::FlacEncoder(const std::string& codecOptions) : Encoder(codecOptions), encoder_(nullptr), pcmBufferSize_(0), encodedSamples_(0)
{ {
@ -133,14 +135,15 @@ FLAC__StreamEncoderWriteStatus FlacEncoder::write_callback(const FLAC__StreamEnc
return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
} }
namespace callback
{
FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder* encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder* encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples,
unsigned current_frame, void* client_data) unsigned current_frame, void* client_data)
{ {
FlacEncoder* flacEncoder = (FlacEncoder*)client_data; FlacEncoder* flacEncoder = (FlacEncoder*)client_data;
return flacEncoder->write_callback(encoder, buffer, bytes, samples, current_frame); return flacEncoder->write_callback(encoder, buffer, bytes, samples, current_frame);
} }
} // namespace callback
void FlacEncoder::initEncoder() void FlacEncoder::initEncoder()
{ {
@ -196,7 +199,9 @@ void FlacEncoder::initEncoder()
throw SnapException("error setting meta data"); throw SnapException("error setting meta data");
// initialize encoder // initialize encoder
init_status = FLAC__stream_encoder_init_stream(encoder_, ::write_callback, nullptr, nullptr, nullptr, this); init_status = FLAC__stream_encoder_init_stream(encoder_, callback::write_callback, nullptr, nullptr, nullptr, this);
if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
throw SnapException("ERROR: initializing encoder: " + string(FLAC__StreamEncoderInitStatusString[init_status])); throw SnapException("ERROR: initializing encoder: " + string(FLAC__StreamEncoderInitStatusString[init_status]));
} }
} // namespace encoder

View file

@ -26,6 +26,8 @@
#include "FLAC/metadata.h" #include "FLAC/metadata.h"
#include "FLAC/stream_encoder.h" #include "FLAC/stream_encoder.h"
namespace encoder
{
class FlacEncoder : public Encoder class FlacEncoder : public Encoder
{ {
@ -53,5 +55,6 @@ protected:
size_t encodedSamples_; size_t encodedSamples_;
}; };
} // namespace encoder
#endif #endif

View file

@ -28,6 +28,8 @@
using namespace std; using namespace std;
namespace encoder
{
OggEncoder::OggEncoder(const std::string& codecOptions) : Encoder(codecOptions), lastGranulepos_(0) OggEncoder::OggEncoder(const std::string& codecOptions) : Encoder(codecOptions), lastGranulepos_(0)
{ {
@ -257,3 +259,5 @@ void OggEncoder::initEncoder()
pos += og_.body_len; pos += og_.body_len;
} }
} }
} // namespace encoder

View file

@ -22,6 +22,9 @@
#include <ogg/ogg.h> #include <ogg/ogg.h>
#include <vorbis/vorbisenc.h> #include <vorbis/vorbisenc.h>
namespace encoder
{
class OggEncoder : public Encoder class OggEncoder : public Encoder
{ {
public: public:
@ -48,5 +51,6 @@ private:
ogg_int64_t lastGranulepos_; ogg_int64_t lastGranulepos_;
}; };
} // namespace encoder
#endif #endif

View file

@ -22,6 +22,9 @@
#include "common/str_compat.hpp" #include "common/str_compat.hpp"
#include "common/utils/string_utils.hpp" #include "common/utils/string_utils.hpp"
namespace encoder
{
#define ID_OPUS 0x4F505553 #define ID_OPUS 0x4F505553
static constexpr opus_int32 const_min_bitrate = 6000; static constexpr opus_int32 const_min_bitrate = 6000;
static constexpr opus_int32 const_max_bitrate = 512000; static constexpr opus_int32 const_max_bitrate = 512000;
@ -36,8 +39,6 @@ void assign(void* pointer, T val)
} }
} // namespace } // namespace
// TODO:
// - handle variable chunk durations (now it's fixed to 10ms)
OpusEncoder::OpusEncoder(const std::string& codecOptions) : Encoder(codecOptions), enc_(nullptr) OpusEncoder::OpusEncoder(const std::string& codecOptions) : Encoder(codecOptions), enc_(nullptr)
{ {
@ -152,6 +153,9 @@ void OpusEncoder::initEncoder()
} }
// TODO:
// handle variable chunk durations, now it's fixed to a "stream_buffer" value of
// 5, 10, 20, 40, 60
void OpusEncoder::encode(const msg::PcmChunk* chunk) void OpusEncoder::encode(const msg::PcmChunk* chunk)
{ {
int samples_per_channel = chunk->getFrameCount(); int samples_per_channel = chunk->getFrameCount();
@ -179,3 +183,5 @@ void OpusEncoder::encode(const msg::PcmChunk* chunk)
<< '\n'; << '\n';
} }
} }
} // namespace encoder

View file

@ -22,6 +22,9 @@
#include <opus/opus.h> #include <opus/opus.h>
namespace encoder
{
class OpusEncoder : public Encoder class OpusEncoder : public Encoder
{ {
public: public:
@ -35,6 +38,8 @@ public:
protected: protected:
void initEncoder() override; void initEncoder() override;
OpusEncoder* enc_; ::OpusEncoder* enc_;
std::vector<u_char> encoded_; std::vector<u_char> encoded_;
}; };
} // namespace encoder

View file

@ -21,6 +21,9 @@
#include <memory> #include <memory>
namespace encoder
{
#define ID_RIFF 0x46464952 #define ID_RIFF 0x46464952
#define ID_WAVE 0x45564157 #define ID_WAVE 0x45564157
#define ID_FMT 0x20746d66 #define ID_FMT 0x20746d66
@ -76,3 +79,5 @@ std::string PcmEncoder::name() const
{ {
return "pcm"; return "pcm";
} }
} // namespace encoder

View file

@ -20,6 +20,8 @@
#define PCM_ENCODER_H #define PCM_ENCODER_H
#include "encoder.hpp" #include "encoder.hpp"
namespace encoder
{
class PcmEncoder : public Encoder class PcmEncoder : public Encoder
{ {
@ -32,5 +34,6 @@ protected:
void initEncoder() override; void initEncoder() override;
}; };
} // namespace encoder
#endif #endif

View file

@ -164,8 +164,8 @@ int main(int argc, char* argv[])
if (settings.stream.codec.find(":?") != string::npos) if (settings.stream.codec.find(":?") != string::npos)
{ {
EncoderFactory encoderFactory; encoder::EncoderFactory encoderFactory;
std::unique_ptr<Encoder> encoder(encoderFactory.createEncoder(settings.stream.codec)); std::unique_ptr<encoder::Encoder> encoder(encoderFactory.createEncoder(settings.stream.codec));
if (encoder) if (encoder)
{ {
cout << "Options for codec \"" << encoder->name() << "\":\n" cout << "Options for codec \"" << encoder->name() << "\":\n"

View file

@ -33,7 +33,7 @@ using namespace std;
PcmStream::PcmStream(PcmListener* pcmListener, const StreamUri& uri) : active_(false), pcmListener_(pcmListener), uri_(uri), pcmReadMs_(20), state_(kIdle) PcmStream::PcmStream(PcmListener* pcmListener, const StreamUri& uri) : active_(false), pcmListener_(pcmListener), uri_(uri), pcmReadMs_(20), state_(kIdle)
{ {
EncoderFactory encoderFactory; encoder::EncoderFactory encoderFactory;
if (uri_.query.find("codec") == uri_.query.end()) if (uri_.query.find("codec") == uri_.query.end())
throw SnapException("Stream URI must have a codec"); throw SnapException("Stream URI must have a codec");
encoder_.reset(encoderFactory.createEncoder(uri_.query["codec"])); encoder_.reset(encoderFactory.createEncoder(uri_.query["codec"]));
@ -144,7 +144,7 @@ void PcmStream::setState(const ReaderState& newState)
} }
void PcmStream::onChunkEncoded(const Encoder* /*encoder*/, msg::PcmChunk* chunk, double duration) void PcmStream::onChunkEncoded(const encoder::Encoder* /*encoder*/, msg::PcmChunk* chunk, double duration)
{ {
// LOG(INFO) << "onChunkEncoded: " << duration << " us\n"; // LOG(INFO) << "onChunkEncoded: " << duration << " us\n";
if (duration <= 0) if (duration <= 0)

View file

@ -64,7 +64,7 @@ public:
* Implements EncoderListener to get the encoded data. * Implements EncoderListener to get the encoded data.
* Data is passed to the PcmListener * Data is passed to the PcmListener
*/ */
class PcmStream : public EncoderListener class PcmStream : public encoder::EncoderListener
{ {
public: public:
/// ctor. Encoded PCM data is passed to the PcmListener /// ctor. Encoded PCM data is passed to the PcmListener
@ -75,7 +75,7 @@ public:
virtual void stop(); virtual void stop();
/// Implementation of EncoderListener::onChunkEncoded /// Implementation of EncoderListener::onChunkEncoded
void onChunkEncoded(const Encoder* encoder, msg::PcmChunk* chunk, double duration) override; void onChunkEncoded(const encoder::Encoder* encoder, msg::PcmChunk* chunk, double duration) override;
virtual std::shared_ptr<msg::CodecHeader> getHeader(); virtual std::shared_ptr<msg::CodecHeader> getHeader();
virtual const StreamUri& getUri() const; virtual const StreamUri& getUri() const;
@ -106,7 +106,7 @@ protected:
SampleFormat sampleFormat_; SampleFormat sampleFormat_;
size_t pcmReadMs_; size_t pcmReadMs_;
size_t dryoutMs_; size_t dryoutMs_;
std::unique_ptr<Encoder> encoder_; std::unique_ptr<encoder::Encoder> encoder_;
std::string name_; std::string name_;
ReaderState state_; ReaderState state_;
std::shared_ptr<msg::StreamTags> meta_; std::shared_ptr<msg::StreamTags> meta_;