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

View file

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

View file

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

View file

@ -27,20 +27,26 @@
using namespace std;
namespace decoder
{
static FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder* decoder, FLAC__byte buffer[], size_t* bytes, void* client_data);
static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder* decoder, const FLAC__Frame* frame, const FLAC__int32* const buffer[],
void* client_data);
static void metadata_callback(const FLAC__StreamDecoder* decoder, const FLAC__StreamMetadata* metadata, void* client_data);
static void error_callback(const FLAC__StreamDecoder* decoder, FLAC__StreamDecoderErrorStatus status, void* client_data);
static msg::CodecHeader* flacHeader = nullptr;
static msg::PcmChunk* flacChunk = nullptr;
static msg::PcmChunk* pcmChunk = nullptr;
static SampleFormat sampleFormat;
static FLAC__StreamDecoder* decoder = nullptr;
namespace callback
{
FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder* decoder, FLAC__byte buffer[], size_t* bytes, void* client_data);
FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder* decoder, const FLAC__Frame* frame, const FLAC__int32* const buffer[],
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);
} // namespace callback
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)
@ -105,8 +111,8 @@ SampleFormat FlacDecoder::setHeader(msg::CodecHeader* chunk)
throw SnapException("ERROR: allocating decoder");
// (void)FLAC__stream_decoder_set_md5_checking(decoder, true);
init_status =
FLAC__stream_decoder_init_stream(decoder, read_callback, nullptr, nullptr, nullptr, nullptr, write_callback, metadata_callback, error_callback, this);
init_status = FLAC__stream_decoder_init_stream(decoder, callback::read_callback, nullptr, nullptr, nullptr, nullptr, callback::write_callback,
callback::metadata_callback, callback::error_callback, this);
if (init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK)
throw SnapException("ERROR: initializing decoder: " + string(FLAC__StreamDecoderInitStatusString[init_status]));
@ -118,7 +124,8 @@ SampleFormat FlacDecoder::setHeader(msg::CodecHeader* chunk)
return sampleFormat;
}
namespace callback
{
FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder* /*decoder*/, FLAC__byte buffer[], size_t* bytes, void* client_data)
{
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";
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 <memory>
namespace decoder
{
struct CacheInfo
{
@ -58,5 +59,6 @@ public:
std::unique_ptr<FLAC__StreamDecoderErrorStatus> lastError_;
};
} // namespace decoder
#endif

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -34,6 +34,8 @@
using namespace std;
namespace encoder
{
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 <string>
namespace encoder
{
class EncoderFactory
{
public:
@ -11,5 +14,6 @@ public:
Encoder* createEncoder(const std::string& codecSettings) const;
};
} // namespace encoder
#endif

View file

@ -25,6 +25,8 @@
using namespace std;
namespace encoder
{
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;
}
namespace callback
{
FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder* encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples,
unsigned current_frame, void* client_data)
{
FlacEncoder* flacEncoder = (FlacEncoder*)client_data;
return flacEncoder->write_callback(encoder, buffer, bytes, samples, current_frame);
}
} // namespace callback
void FlacEncoder::initEncoder()
{
@ -196,7 +199,9 @@ void FlacEncoder::initEncoder()
throw SnapException("error setting meta data");
// 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)
throw SnapException("ERROR: initializing encoder: " + string(FLAC__StreamEncoderInitStatusString[init_status]));
}
} // namespace encoder

View file

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

View file

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

View file

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

View file

@ -22,6 +22,9 @@
#include "common/str_compat.hpp"
#include "common/utils/string_utils.hpp"
namespace encoder
{
#define ID_OPUS 0x4F505553
static constexpr opus_int32 const_min_bitrate = 6000;
static constexpr opus_int32 const_max_bitrate = 512000;
@ -36,8 +39,6 @@ void assign(void* pointer, T val)
}
} // namespace
// TODO:
// - handle variable chunk durations (now it's fixed to 10ms)
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)
{
int samples_per_channel = chunk->getFrameCount();
@ -179,3 +183,5 @@ void OpusEncoder::encode(const msg::PcmChunk* chunk)
<< '\n';
}
}
} // namespace encoder

View file

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

View file

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

View file

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

View file

@ -164,8 +164,8 @@ int main(int argc, char* argv[])
if (settings.stream.codec.find(":?") != string::npos)
{
EncoderFactory encoderFactory;
std::unique_ptr<Encoder> encoder(encoderFactory.createEncoder(settings.stream.codec));
encoder::EncoderFactory encoderFactory;
std::unique_ptr<encoder::Encoder> encoder(encoderFactory.createEncoder(settings.stream.codec));
if (encoder)
{
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)
{
EncoderFactory encoderFactory;
encoder::EncoderFactory encoderFactory;
if (uri_.query.find("codec") == uri_.query.end())
throw SnapException("Stream URI must have a 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";
if (duration <= 0)

View file

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