encoder/Interface: convert PreparedEncoder to abstract class
This commit is contained in:
parent
e7edc02647
commit
b376536a3b
|
@ -26,6 +26,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
struct AudioFormat;
|
||||||
struct Tag;
|
struct Tag;
|
||||||
|
|
||||||
class Encoder {
|
class Encoder {
|
||||||
|
@ -112,19 +113,9 @@ public:
|
||||||
virtual size_t Read(void *dest, size_t length) = 0;
|
virtual size_t Read(void *dest, size_t length) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PreparedEncoder {
|
class PreparedEncoder {
|
||||||
const EncoderPlugin &plugin;
|
public:
|
||||||
|
virtual ~PreparedEncoder() {}
|
||||||
explicit PreparedEncoder(const EncoderPlugin &_plugin)
|
|
||||||
:plugin(_plugin) {}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frees an #Encoder object.
|
|
||||||
*/
|
|
||||||
void Dispose() {
|
|
||||||
plugin.finish(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the object. You must call this prior to using it.
|
* Opens the object. You must call this prior to using it.
|
||||||
|
@ -139,24 +130,16 @@ struct PreparedEncoder {
|
||||||
* may modify the struct to adapt it to its abilities
|
* may modify the struct to adapt it to its abilities
|
||||||
* @return true on success
|
* @return true on success
|
||||||
*/
|
*/
|
||||||
Encoder *Open(AudioFormat &audio_format, Error &error) {
|
virtual Encoder *Open(AudioFormat &audio_format, Error &error) = 0;
|
||||||
return plugin.open(this, audio_format, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get mime type of encoded content.
|
||||||
|
*
|
||||||
|
* @return an constant string, nullptr on failure
|
||||||
|
*/
|
||||||
|
virtual const char *GetMimeType() const {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Get mime type of encoded content.
|
|
||||||
*
|
|
||||||
* @return an constant string, nullptr on failure
|
|
||||||
*/
|
|
||||||
static inline const char *
|
|
||||||
encoder_get_mime_type(PreparedEncoder *encoder)
|
|
||||||
{
|
|
||||||
/* this method is optional */
|
|
||||||
return encoder->plugin.get_mime_type != nullptr
|
|
||||||
? encoder->plugin.get_mime_type(encoder)
|
|
||||||
: nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -20,9 +20,7 @@
|
||||||
#ifndef MPD_ENCODER_PLUGIN_HXX
|
#ifndef MPD_ENCODER_PLUGIN_HXX
|
||||||
#define MPD_ENCODER_PLUGIN_HXX
|
#define MPD_ENCODER_PLUGIN_HXX
|
||||||
|
|
||||||
struct PreparedEncoder;
|
class PreparedEncoder;
|
||||||
class Encoder;
|
|
||||||
struct AudioFormat;
|
|
||||||
struct ConfigBlock;
|
struct ConfigBlock;
|
||||||
class Error;
|
class Error;
|
||||||
|
|
||||||
|
@ -31,14 +29,6 @@ struct EncoderPlugin {
|
||||||
|
|
||||||
PreparedEncoder *(*init)(const ConfigBlock &block,
|
PreparedEncoder *(*init)(const ConfigBlock &block,
|
||||||
Error &error);
|
Error &error);
|
||||||
|
|
||||||
void (*finish)(PreparedEncoder *encoder);
|
|
||||||
|
|
||||||
Encoder *(*open)(PreparedEncoder *encoder,
|
|
||||||
AudioFormat &audio_format,
|
|
||||||
Error &error);
|
|
||||||
|
|
||||||
const char *(*get_mime_type)(PreparedEncoder *encoder);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -88,14 +88,18 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PreparedFlacEncoder {
|
class PreparedFlacEncoder final : public PreparedEncoder {
|
||||||
PreparedEncoder encoder;
|
|
||||||
|
|
||||||
unsigned compression;
|
unsigned compression;
|
||||||
|
|
||||||
PreparedFlacEncoder():encoder(flac_encoder_plugin) {}
|
public:
|
||||||
|
|
||||||
bool Configure(const ConfigBlock &block, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
|
/* virtual methods from class PreparedEncoder */
|
||||||
|
Encoder *Open(AudioFormat &audio_format, Error &) override;
|
||||||
|
|
||||||
|
const char *GetMimeType() const override {
|
||||||
|
return "audio/flac";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr Domain flac_encoder_domain("vorbis_encoder");
|
static constexpr Domain flac_encoder_domain("vorbis_encoder");
|
||||||
|
@ -119,17 +123,7 @@ flac_encoder_init(const ConfigBlock &block, Error &error)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return &encoder->encoder;
|
return encoder;
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
flac_encoder_finish(PreparedEncoder *_encoder)
|
|
||||||
{
|
|
||||||
auto *encoder = (PreparedFlacEncoder *)_encoder;
|
|
||||||
|
|
||||||
/* the real libFLAC cleanup was already performed by
|
|
||||||
flac_encoder_close(), so no real work here */
|
|
||||||
delete encoder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -190,10 +184,9 @@ FlacEncoder::Init(Error &error)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Encoder *
|
Encoder *
|
||||||
flac_encoder_open(PreparedEncoder *_encoder, AudioFormat &audio_format, Error &error)
|
PreparedFlacEncoder::Open(AudioFormat &audio_format, Error &error)
|
||||||
{
|
{
|
||||||
auto *encoder = (PreparedFlacEncoder *)_encoder;
|
|
||||||
unsigned bits_per_sample;
|
unsigned bits_per_sample;
|
||||||
|
|
||||||
/* FIXME: flac should support 32bit as well */
|
/* FIXME: flac should support 32bit as well */
|
||||||
|
@ -222,7 +215,7 @@ flac_encoder_open(PreparedEncoder *_encoder, AudioFormat &audio_format, Error &e
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!flac_encoder_setup(fse, encoder->compression,
|
if (!flac_encoder_setup(fse, compression,
|
||||||
audio_format, bits_per_sample, error)) {
|
audio_format, bits_per_sample, error)) {
|
||||||
FLAC__stream_encoder_delete(fse);
|
FLAC__stream_encoder_delete(fse);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -304,17 +297,8 @@ FlacEncoder::Write(const void *data, size_t length, Error &error)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
|
||||||
flac_encoder_get_mime_type(gcc_unused PreparedEncoder *_encoder)
|
|
||||||
{
|
|
||||||
return "audio/flac";
|
|
||||||
}
|
|
||||||
|
|
||||||
const EncoderPlugin flac_encoder_plugin = {
|
const EncoderPlugin flac_encoder_plugin = {
|
||||||
"flac",
|
"flac",
|
||||||
flac_encoder_init,
|
flac_encoder_init,
|
||||||
flac_encoder_finish,
|
|
||||||
flac_encoder_open,
|
|
||||||
flac_encoder_get_mime_type,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -53,15 +53,19 @@ public:
|
||||||
size_t Read(void *dest, size_t length) override;
|
size_t Read(void *dest, size_t length) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PreparedLameEncoder final {
|
class PreparedLameEncoder final : public PreparedEncoder {
|
||||||
PreparedEncoder encoder;
|
|
||||||
|
|
||||||
float quality;
|
float quality;
|
||||||
int bitrate;
|
int bitrate;
|
||||||
|
|
||||||
PreparedLameEncoder():encoder(lame_encoder_plugin) {}
|
public:
|
||||||
|
|
||||||
bool Configure(const ConfigBlock &block, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
|
/* virtual methods from class PreparedEncoder */
|
||||||
|
Encoder *Open(AudioFormat &audio_format, Error &) override;
|
||||||
|
|
||||||
|
const char *GetMimeType() const override {
|
||||||
|
return "audio/mpeg";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr Domain lame_encoder_domain("lame_encoder");
|
static constexpr Domain lame_encoder_domain("lame_encoder");
|
||||||
|
@ -126,17 +130,7 @@ lame_encoder_init(const ConfigBlock &block, Error &error)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return &encoder->encoder;
|
return encoder;
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
lame_encoder_finish(PreparedEncoder *_encoder)
|
|
||||||
{
|
|
||||||
auto *encoder = (PreparedLameEncoder *)_encoder;
|
|
||||||
|
|
||||||
/* the real liblame cleanup was already performed by
|
|
||||||
lame_encoder_close(), so no real work here */
|
|
||||||
delete encoder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -193,12 +187,9 @@ lame_encoder_setup(lame_global_flags *gfp, float quality, int bitrate,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Encoder *
|
Encoder *
|
||||||
lame_encoder_open(PreparedEncoder *_encoder, AudioFormat &audio_format,
|
PreparedLameEncoder::Open(AudioFormat &audio_format, Error &error)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
auto *encoder = (PreparedLameEncoder *)_encoder;
|
|
||||||
|
|
||||||
audio_format.format = SampleFormat::S16;
|
audio_format.format = SampleFormat::S16;
|
||||||
audio_format.channels = 2;
|
audio_format.channels = 2;
|
||||||
|
|
||||||
|
@ -208,7 +199,7 @@ lame_encoder_open(PreparedEncoder *_encoder, AudioFormat &audio_format,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lame_encoder_setup(gfp, encoder->quality, encoder->bitrate,
|
if (!lame_encoder_setup(gfp, quality, bitrate,
|
||||||
audio_format, error)) {
|
audio_format, error)) {
|
||||||
lame_close(gfp);
|
lame_close(gfp);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -269,16 +260,7 @@ LameEncoder::Read(void *dest, size_t length)
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
|
||||||
lame_encoder_get_mime_type(gcc_unused PreparedEncoder *_encoder)
|
|
||||||
{
|
|
||||||
return "audio/mpeg";
|
|
||||||
}
|
|
||||||
|
|
||||||
const EncoderPlugin lame_encoder_plugin = {
|
const EncoderPlugin lame_encoder_plugin = {
|
||||||
"lame",
|
"lame",
|
||||||
lame_encoder_init,
|
lame_encoder_init,
|
||||||
lame_encoder_finish,
|
|
||||||
lame_encoder_open,
|
|
||||||
lame_encoder_get_mime_type,
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,8 +23,6 @@
|
||||||
#include "util/DynamicFifoBuffer.hxx"
|
#include "util/DynamicFifoBuffer.hxx"
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
class NullEncoder final : public Encoder {
|
class NullEncoder final : public Encoder {
|
||||||
DynamicFifoBuffer<uint8_t> buffer;
|
DynamicFifoBuffer<uint8_t> buffer;
|
||||||
|
|
||||||
|
@ -44,40 +42,22 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PreparedNullEncoder final {
|
class PreparedNullEncoder final : public PreparedEncoder {
|
||||||
PreparedEncoder encoder;
|
public:
|
||||||
|
/* virtual methods from class PreparedEncoder */
|
||||||
PreparedNullEncoder()
|
Encoder *Open(AudioFormat &, Error &) override {
|
||||||
:encoder(null_encoder_plugin) {}
|
return new NullEncoder();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static PreparedEncoder *
|
static PreparedEncoder *
|
||||||
null_encoder_init(gcc_unused const ConfigBlock &block,
|
null_encoder_init(gcc_unused const ConfigBlock &block,
|
||||||
gcc_unused Error &error)
|
gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
auto *encoder = new PreparedNullEncoder();
|
return new PreparedNullEncoder();
|
||||||
return &encoder->encoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
null_encoder_finish(PreparedEncoder *_encoder)
|
|
||||||
{
|
|
||||||
auto *encoder = (PreparedNullEncoder *)_encoder;
|
|
||||||
delete encoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Encoder *
|
|
||||||
null_encoder_open(gcc_unused PreparedEncoder *encoder,
|
|
||||||
gcc_unused AudioFormat &audio_format,
|
|
||||||
gcc_unused Error &error)
|
|
||||||
{
|
|
||||||
return new NullEncoder();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const EncoderPlugin null_encoder_plugin = {
|
const EncoderPlugin null_encoder_plugin = {
|
||||||
"null",
|
"null",
|
||||||
null_encoder_init,
|
null_encoder_init,
|
||||||
null_encoder_finish,
|
|
||||||
null_encoder_open,
|
|
||||||
nullptr,
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -77,20 +77,20 @@ private:
|
||||||
void GenerateTags();
|
void GenerateTags();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PreparedOpusEncoder {
|
class PreparedOpusEncoder final : public PreparedEncoder {
|
||||||
/** the base class */
|
|
||||||
PreparedEncoder encoder;
|
|
||||||
|
|
||||||
/* configuration */
|
|
||||||
|
|
||||||
opus_int32 bitrate;
|
opus_int32 bitrate;
|
||||||
int complexity;
|
int complexity;
|
||||||
int signal;
|
int signal;
|
||||||
|
|
||||||
PreparedOpusEncoder():encoder(opus_encoder_plugin) {}
|
public:
|
||||||
|
|
||||||
bool Configure(const ConfigBlock &block, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
Encoder *Open(AudioFormat &audio_format, Error &error);
|
|
||||||
|
/* virtual methods from class PreparedEncoder */
|
||||||
|
Encoder *Open(AudioFormat &audio_format, Error &) override;
|
||||||
|
|
||||||
|
const char *GetMimeType() const override {
|
||||||
|
return "audio/ogg";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr Domain opus_encoder_domain("opus_encoder");
|
static constexpr Domain opus_encoder_domain("opus_encoder");
|
||||||
|
@ -146,17 +146,7 @@ opus_encoder_init(const ConfigBlock &block, Error &error)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return &encoder->encoder;
|
return encoder;
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
opus_encoder_finish(PreparedEncoder *_encoder)
|
|
||||||
{
|
|
||||||
auto *encoder = (PreparedOpusEncoder *)_encoder;
|
|
||||||
|
|
||||||
/* the real libopus cleanup was already performed by
|
|
||||||
opus_encoder_close(), so no real work here */
|
|
||||||
delete encoder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OpusEncoder::OpusEncoder(AudioFormat &_audio_format, ::OpusEncoder *_enc)
|
OpusEncoder::OpusEncoder(AudioFormat &_audio_format, ::OpusEncoder *_enc)
|
||||||
|
@ -214,15 +204,6 @@ PreparedOpusEncoder::Open(AudioFormat &audio_format, Error &error)
|
||||||
return new OpusEncoder(audio_format, enc);
|
return new OpusEncoder(audio_format, enc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Encoder *
|
|
||||||
opus_encoder_open(PreparedEncoder *_encoder,
|
|
||||||
AudioFormat &audio_format,
|
|
||||||
Error &error)
|
|
||||||
{
|
|
||||||
auto &encoder = *(PreparedOpusEncoder *)_encoder;
|
|
||||||
return encoder.Open(audio_format, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
OpusEncoder::~OpusEncoder()
|
OpusEncoder::~OpusEncoder()
|
||||||
{
|
{
|
||||||
stream.Deinitialize();
|
stream.Deinitialize();
|
||||||
|
@ -405,18 +386,9 @@ OpusEncoder::Read(void *dest, size_t length)
|
||||||
return stream.PageOut(dest, length);
|
return stream.PageOut(dest, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
|
||||||
opus_encoder_get_mime_type(gcc_unused PreparedEncoder *_encoder)
|
|
||||||
{
|
|
||||||
return "audio/ogg";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const EncoderPlugin opus_encoder_plugin = {
|
const EncoderPlugin opus_encoder_plugin = {
|
||||||
"opus",
|
"opus",
|
||||||
opus_encoder_init,
|
opus_encoder_init,
|
||||||
opus_encoder_finish,
|
|
||||||
opus_encoder_open,
|
|
||||||
opus_encoder_get_mime_type,
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -84,16 +84,18 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PreparedShineEncoder {
|
class PreparedShineEncoder final : public PreparedEncoder {
|
||||||
PreparedEncoder encoder;
|
|
||||||
|
|
||||||
shine_config_t config;
|
shine_config_t config;
|
||||||
|
|
||||||
PreparedShineEncoder():encoder(shine_encoder_plugin) {}
|
public:
|
||||||
|
|
||||||
bool Configure(const ConfigBlock &block, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
bool Setup(Error &error);
|
/* virtual methods from class PreparedEncoder */
|
||||||
|
Encoder *Open(AudioFormat &audio_format, Error &) override;
|
||||||
|
|
||||||
|
const char *GetMimeType() const override {
|
||||||
|
return "audio/mpeg";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
|
@ -117,15 +119,7 @@ shine_encoder_init(const ConfigBlock &block, Error &error)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return &encoder->encoder;
|
return encoder;
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
shine_encoder_finish(PreparedEncoder *_encoder)
|
|
||||||
{
|
|
||||||
auto *encoder = (PreparedShineEncoder *)_encoder;
|
|
||||||
|
|
||||||
delete encoder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static shine_t
|
static shine_t
|
||||||
|
@ -159,13 +153,10 @@ SetupShine(shine_config_t config, AudioFormat &audio_format,
|
||||||
return shine;
|
return shine;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Encoder *
|
Encoder *
|
||||||
shine_encoder_open(PreparedEncoder *_encoder, AudioFormat &audio_format,
|
PreparedShineEncoder::Open(AudioFormat &audio_format, Error &error)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
auto *encoder = (PreparedShineEncoder *)_encoder;
|
auto shine = SetupShine(config, audio_format, error);
|
||||||
|
|
||||||
auto shine = SetupShine(encoder->config, audio_format, error);
|
|
||||||
if (!shine)
|
if (!shine)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -238,16 +229,7 @@ ShineEncoder::Flush(gcc_unused Error &error)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
|
||||||
shine_encoder_get_mime_type(gcc_unused PreparedEncoder *_encoder)
|
|
||||||
{
|
|
||||||
return "audio/mpeg";
|
|
||||||
}
|
|
||||||
|
|
||||||
const EncoderPlugin shine_encoder_plugin = {
|
const EncoderPlugin shine_encoder_plugin = {
|
||||||
"shine",
|
"shine",
|
||||||
shine_encoder_init,
|
shine_encoder_init,
|
||||||
shine_encoder_finish,
|
|
||||||
shine_encoder_open,
|
|
||||||
shine_encoder_get_mime_type,
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -72,15 +72,19 @@ public:
|
||||||
size_t Read(void *dest, size_t length) override;
|
size_t Read(void *dest, size_t length) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PreparedTwolameEncoder final {
|
class PreparedTwolameEncoder final : public PreparedEncoder {
|
||||||
PreparedEncoder encoder;
|
|
||||||
|
|
||||||
float quality;
|
float quality;
|
||||||
int bitrate;
|
int bitrate;
|
||||||
|
|
||||||
PreparedTwolameEncoder():encoder(twolame_encoder_plugin) {}
|
public:
|
||||||
|
|
||||||
bool Configure(const ConfigBlock &block, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
|
/* virtual methods from class PreparedEncoder */
|
||||||
|
Encoder *Open(AudioFormat &audio_format, Error &) override;
|
||||||
|
|
||||||
|
const char *GetMimeType() const override {
|
||||||
|
return "audio/mpeg";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr Domain twolame_encoder_domain("twolame_encoder");
|
static constexpr Domain twolame_encoder_domain("twolame_encoder");
|
||||||
|
@ -148,17 +152,7 @@ twolame_encoder_init(const ConfigBlock &block, Error &error_r)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return &encoder->encoder;
|
return encoder;
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
twolame_encoder_finish(PreparedEncoder *_encoder)
|
|
||||||
{
|
|
||||||
auto *encoder = (PreparedTwolameEncoder *)_encoder;
|
|
||||||
|
|
||||||
/* the real libtwolame cleanup was already performed by
|
|
||||||
twolame_encoder_close(), so no real work here */
|
|
||||||
delete encoder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -210,12 +204,9 @@ twolame_encoder_setup(twolame_options *options, float quality, int bitrate,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Encoder *
|
Encoder *
|
||||||
twolame_encoder_open(PreparedEncoder *_encoder, AudioFormat &audio_format,
|
PreparedTwolameEncoder::Open(AudioFormat &audio_format, Error &error)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
auto *encoder = (PreparedTwolameEncoder *)_encoder;
|
|
||||||
|
|
||||||
audio_format.format = SampleFormat::S16;
|
audio_format.format = SampleFormat::S16;
|
||||||
audio_format.channels = 2;
|
audio_format.channels = 2;
|
||||||
|
|
||||||
|
@ -225,7 +216,7 @@ twolame_encoder_open(PreparedEncoder *_encoder, AudioFormat &audio_format,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!twolame_encoder_setup(options, encoder->quality, encoder->bitrate,
|
if (!twolame_encoder_setup(options, quality, bitrate,
|
||||||
audio_format, error)) {
|
audio_format, error)) {
|
||||||
twolame_close(&options);
|
twolame_close(&options);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -291,16 +282,7 @@ TwolameEncoder::Read(void *dest, size_t length)
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
|
||||||
twolame_encoder_get_mime_type(gcc_unused PreparedEncoder *_encoder)
|
|
||||||
{
|
|
||||||
return "audio/mpeg";
|
|
||||||
}
|
|
||||||
|
|
||||||
const EncoderPlugin twolame_encoder_plugin = {
|
const EncoderPlugin twolame_encoder_plugin = {
|
||||||
"twolame",
|
"twolame",
|
||||||
twolame_encoder_init,
|
twolame_encoder_init,
|
||||||
twolame_encoder_finish,
|
|
||||||
twolame_encoder_open,
|
|
||||||
twolame_encoder_get_mime_type,
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -73,18 +73,19 @@ private:
|
||||||
void Clear();
|
void Clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PreparedVorbisEncoder {
|
class PreparedVorbisEncoder final : public PreparedEncoder {
|
||||||
/** the base class */
|
|
||||||
PreparedEncoder encoder;
|
|
||||||
|
|
||||||
/* configuration */
|
|
||||||
|
|
||||||
float quality;
|
float quality;
|
||||||
int bitrate;
|
int bitrate;
|
||||||
|
|
||||||
PreparedVorbisEncoder():encoder(vorbis_encoder_plugin) {}
|
public:
|
||||||
|
|
||||||
bool Configure(const ConfigBlock &block, Error &error);
|
bool Configure(const ConfigBlock &block, Error &error);
|
||||||
|
|
||||||
|
/* virtual methods from class PreparedEncoder */
|
||||||
|
Encoder *Open(AudioFormat &audio_format, Error &) override;
|
||||||
|
|
||||||
|
const char *GetMimeType() const override {
|
||||||
|
return "audio/ogg";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr Domain vorbis_encoder_domain("vorbis_encoder");
|
static constexpr Domain vorbis_encoder_domain("vorbis_encoder");
|
||||||
|
@ -148,17 +149,7 @@ vorbis_encoder_init(const ConfigBlock &block, Error &error)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return &encoder->encoder;
|
return encoder;
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
vorbis_encoder_finish(PreparedEncoder *_encoder)
|
|
||||||
{
|
|
||||||
auto *encoder = (PreparedVorbisEncoder *)_encoder;
|
|
||||||
|
|
||||||
/* the real libvorbis/libogg cleanup was already performed by
|
|
||||||
vorbis_encoder_close(), so no real work here */
|
|
||||||
delete encoder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -228,15 +219,11 @@ VorbisEncoder::SendHeader()
|
||||||
vorbis_comment_clear(&vc);
|
vorbis_comment_clear(&vc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Encoder *
|
Encoder *
|
||||||
vorbis_encoder_open(PreparedEncoder *_encoder,
|
PreparedVorbisEncoder::Open(AudioFormat &audio_format, Error &error)
|
||||||
AudioFormat &audio_format,
|
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
auto &encoder = *(PreparedVorbisEncoder *)_encoder;
|
|
||||||
|
|
||||||
auto *e = new VorbisEncoder();
|
auto *e = new VorbisEncoder();
|
||||||
if (!e->Open(encoder.quality, encoder.bitrate, audio_format, error)) {
|
if (!e->Open(quality, bitrate, audio_format, error)) {
|
||||||
delete e;
|
delete e;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -348,16 +335,7 @@ VorbisEncoder::Write(const void *data, size_t length, gcc_unused Error &error)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
|
||||||
vorbis_encoder_get_mime_type(gcc_unused PreparedEncoder *_encoder)
|
|
||||||
{
|
|
||||||
return "audio/ogg";
|
|
||||||
}
|
|
||||||
|
|
||||||
const EncoderPlugin vorbis_encoder_plugin = {
|
const EncoderPlugin vorbis_encoder_plugin = {
|
||||||
"vorbis",
|
"vorbis",
|
||||||
vorbis_encoder_init,
|
vorbis_encoder_init,
|
||||||
vorbis_encoder_finish,
|
|
||||||
vorbis_encoder_open,
|
|
||||||
vorbis_encoder_get_mime_type,
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -44,10 +44,15 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PreparedWaveEncoder {
|
class PreparedWaveEncoder final : public PreparedEncoder {
|
||||||
PreparedEncoder encoder;
|
/* virtual methods from class PreparedEncoder */
|
||||||
|
Encoder *Open(AudioFormat &audio_format, Error &) override {
|
||||||
|
return new WaveEncoder(audio_format);
|
||||||
|
}
|
||||||
|
|
||||||
PreparedWaveEncoder():encoder(wave_encoder_plugin) {}
|
const char *GetMimeType() const override {
|
||||||
|
return "audio/wav";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WaveHeader {
|
struct WaveHeader {
|
||||||
|
@ -96,16 +101,7 @@ static PreparedEncoder *
|
||||||
wave_encoder_init(gcc_unused const ConfigBlock &block,
|
wave_encoder_init(gcc_unused const ConfigBlock &block,
|
||||||
gcc_unused Error &error)
|
gcc_unused Error &error)
|
||||||
{
|
{
|
||||||
auto *encoder = new PreparedWaveEncoder();
|
return new PreparedWaveEncoder();
|
||||||
return &encoder->encoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
wave_encoder_finish(PreparedEncoder *_encoder)
|
|
||||||
{
|
|
||||||
auto *encoder = (PreparedWaveEncoder *)_encoder;
|
|
||||||
|
|
||||||
delete encoder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WaveEncoder::WaveEncoder(AudioFormat &audio_format)
|
WaveEncoder::WaveEncoder(AudioFormat &audio_format)
|
||||||
|
@ -151,14 +147,6 @@ WaveEncoder::WaveEncoder(AudioFormat &audio_format)
|
||||||
buffer.Append(sizeof(*header));
|
buffer.Append(sizeof(*header));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Encoder *
|
|
||||||
wave_encoder_open(gcc_unused PreparedEncoder *_encoder,
|
|
||||||
AudioFormat &audio_format,
|
|
||||||
gcc_unused Error &error)
|
|
||||||
{
|
|
||||||
return new WaveEncoder(audio_format);
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
pcm16_to_wave(uint16_t *dst16, const uint16_t *src16, size_t length)
|
pcm16_to_wave(uint16_t *dst16, const uint16_t *src16, size_t length)
|
||||||
{
|
{
|
||||||
|
@ -239,16 +227,7 @@ WaveEncoder::Write(const void *src, size_t length,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
|
||||||
wave_encoder_get_mime_type(gcc_unused PreparedEncoder *_encoder)
|
|
||||||
{
|
|
||||||
return "audio/wav";
|
|
||||||
}
|
|
||||||
|
|
||||||
const EncoderPlugin wave_encoder_plugin = {
|
const EncoderPlugin wave_encoder_plugin = {
|
||||||
"wave",
|
"wave",
|
||||||
wave_encoder_init,
|
wave_encoder_init,
|
||||||
wave_encoder_finish,
|
|
||||||
wave_encoder_open,
|
|
||||||
wave_encoder_get_mime_type,
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -76,8 +76,7 @@ class RecorderOutput {
|
||||||
:base(recorder_output_plugin) {}
|
:base(recorder_output_plugin) {}
|
||||||
|
|
||||||
~RecorderOutput() {
|
~RecorderOutput() {
|
||||||
if (prepared_encoder != nullptr)
|
delete prepared_encoder;
|
||||||
prepared_encoder->Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Initialize(const ConfigBlock &block, Error &error_r) {
|
bool Initialize(const ConfigBlock &block, Error &error_r) {
|
||||||
|
|
|
@ -45,7 +45,7 @@ class EventLoop;
|
||||||
class ServerSocket;
|
class ServerSocket;
|
||||||
class HttpdClient;
|
class HttpdClient;
|
||||||
class Page;
|
class Page;
|
||||||
struct PreparedEncoder;
|
class PreparedEncoder;
|
||||||
class Encoder;
|
class Encoder;
|
||||||
struct Tag;
|
struct Tag;
|
||||||
|
|
||||||
|
|
|
@ -63,9 +63,7 @@ HttpdOutput::~HttpdOutput()
|
||||||
if (metadata != nullptr)
|
if (metadata != nullptr)
|
||||||
metadata->Unref();
|
metadata->Unref();
|
||||||
|
|
||||||
if (prepared_encoder != nullptr)
|
delete prepared_encoder;
|
||||||
prepared_encoder->Dispose();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
|
@ -128,7 +126,7 @@ HttpdOutput::Configure(const ConfigBlock &block, Error &error)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* determine content type */
|
/* determine content type */
|
||||||
content_type = encoder_get_mime_type(prepared_encoder);
|
content_type = prepared_encoder->GetMimeType();
|
||||||
if (content_type == nullptr)
|
if (content_type == nullptr)
|
||||||
content_type = "application/octet-stream";
|
content_type = "application/octet-stream";
|
||||||
|
|
||||||
|
|
|
@ -111,7 +111,7 @@ int main(int argc, char **argv)
|
||||||
EncoderToOutputStream(os, *encoder);
|
EncoderToOutputStream(os, *encoder);
|
||||||
|
|
||||||
delete encoder;
|
delete encoder;
|
||||||
p_encoder->Dispose();
|
delete p_encoder;
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
|
|
|
@ -103,7 +103,7 @@ main(gcc_unused int argc, gcc_unused char **argv)
|
||||||
EncoderToOutputStream(os, *encoder);
|
EncoderToOutputStream(os, *encoder);
|
||||||
|
|
||||||
delete encoder;
|
delete encoder;
|
||||||
p_encoder->Dispose();
|
delete p_encoder;
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
|
|
Loading…
Reference in New Issue