summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVegard Storheil Eriksen <zyp@jvnv.net>2011-01-06 05:29:39 +0100
committerVegard Storheil Eriksen <zyp@jvnv.net>2011-01-06 05:29:47 +0100
commit6f2fefdd9ff5f8561b3538efb5eb0765a9b4a141 (patch)
treede37cd2d500a777344b611321ac45bce66ad5c26
parentffd8b5976af7e80425c7cf043528212528877b16 (diff)
Replaced iostream-based decoder-encoder chain with direct chain.
-rw-r--r--decoder.cpp13
-rw-r--r--decoder.h58
-rw-r--r--decoders/mpg123_decoder.cpp8
-rw-r--r--decoders/mpg123_decoder.h11
-rw-r--r--encoder.cpp13
-rw-r--r--encoder.h56
-rw-r--r--encoders/lame_encoder.cpp10
-rw-r--r--encoders/lame_encoder.h10
-rw-r--r--main.cpp4
-rw-r--r--music.cpp17
-rw-r--r--transcode.cpp18
-rw-r--r--transcode.h22
12 files changed, 72 insertions, 168 deletions
diff --git a/decoder.cpp b/decoder.cpp
index c362745..9330c6e 100644
--- a/decoder.cpp
+++ b/decoder.cpp
@@ -6,19 +6,14 @@
#include <map>
-DecoderFilter::DecoderFilter(DecoderBase::p decoder_) {
- decoder = decoder_;
-}
-
-typedef boost::function<DecoderBase::p ()> DecoderFactory;
+typedef boost::function<Decoder::p (const std::string&)> DecoderFactory;
std::map<std::string, DecoderFactory> decoder_factories;
-void decoder::init() {
+void Decoder::init() {
mpg123_init(); // initialize the mpg123 library
decoder_factories["mpg123"] = boost::factory<boost::shared_ptr<DecoderMpg123> >();
}
-//! Construct a filter with the given decoder.
-DecoderFilter::p decoder::get_decoder(const std::string& name) {
- return DecoderFilter::p(new DecoderFilter(decoder_factories[name]()));
+Decoder::p Decoder::get(const std::string& name, const std::string& filename) {
+ return decoder_factories[name](filename);
}
diff --git a/decoder.h b/decoder.h
index d58dcf1..a1d857f 100644
--- a/decoder.h
+++ b/decoder.h
@@ -1,56 +1,32 @@
#ifndef DECODER_H
#define DECODER_H
-#include <boost/iostreams/concepts.hpp>
-#include <boost/iostreams/operations.hpp>
#include <boost/shared_ptr.hpp>
-#include <boost/function.hpp>
#include <string>
-class DecoderBase {
- friend class DecoderFilter;
-
- protected:
- typedef boost::function<std::size_t (char*, std::size_t)> ReadFunc;
-
- virtual size_t decode(ReadFunc read, uint8_t *output, size_t output_size) = 0;
-
+//! Interface for classes outputting raw audio.
+class RawAudioSource {
public:
- typedef boost::shared_ptr<DecoderBase> p;
- virtual ~DecoderBase() {}
-};
-
-//! Input filter to hold a decoder in a filter chain.
-class DecoderFilter : public boost::iostreams::multichar_input_filter {
- private:
- DecoderBase::p decoder;
+ typedef boost::shared_ptr<RawAudioSource> p;
- //! Functor binding a source to a read function.
- template<class T>
- struct ReadFunc {
- T& s;
-
- ReadFunc(T& s_) : s(s_) {}
-
- std::size_t operator()(char* buf, std::size_t buf_size) {
- return boost::iostreams::read(s, buf, buf_size);
- }
- };
-
- public:
- typedef boost::shared_ptr<DecoderFilter> p;
- DecoderFilter(DecoderBase::p decoder_);
+ //! Virtual destructor.
+ virtual ~RawAudioSource() {}
- template<typename Source>
- std::streamsize read(Source& src, char *s, std::streamsize n) {
- return decoder->decode(ReadFunc<Source>(src), (uint8_t*)s, n);
- }
+ //! Read into provided buffer.
+ virtual std::size_t read(char* buf, std::size_t buf_size) = 0;
};
-namespace decoder {
- void init();
- DecoderFilter::p get_decoder(const std::string& name);
+//! Decoder base class.
+class Decoder : public RawAudioSource {
+ public:
+ typedef boost::shared_ptr<Decoder> p;
+
+ //! Initialize decoders.
+ static void init();
+
+ //! Construct and return requested decoder.
+ static p get(const std::string& name, const std::string& filename);
};
#endif
diff --git a/decoders/mpg123_decoder.cpp b/decoders/mpg123_decoder.cpp
index 0618320..8b3d9b4 100644
--- a/decoders/mpg123_decoder.cpp
+++ b/decoders/mpg123_decoder.cpp
@@ -5,7 +5,7 @@
#include <iostream>
#include <stdexcept>
-DecoderMpg123::DecoderMpg123() {
+DecoderMpg123::DecoderMpg123(const std::string& filename) : ifile(filename.c_str()) {
int error;
handle = mpg123_new("generic", &error);
if(error) {
@@ -49,10 +49,10 @@ size_t DecoderMpg123::decode(const uint8_t *input, size_t input_size, uint8_t *o
return output_written;
}
-size_t DecoderMpg123::decode(ReadFunc read, uint8_t *output, size_t output_size) {
+std::size_t DecoderMpg123::read(char* buf, std::size_t buf_size) {
char src_data[0x2000];
- std::streamsize src_read = read(src_data, 0x2000);
+ std::streamsize src_read = ifile.get(src_data, 0x2000).gcount();
if(src_read < 0)
src_read = 0;
- return decode((const uint8_t*)src_data, src_read, (uint8_t*)output, output_size);
+ return decode((const uint8_t*)src_data, src_read, (uint8_t*)buf, buf_size);
}
diff --git a/decoders/mpg123_decoder.h b/decoders/mpg123_decoder.h
index 5a637af..f71dbe7 100644
--- a/decoders/mpg123_decoder.h
+++ b/decoders/mpg123_decoder.h
@@ -3,20 +3,21 @@
#include "decoder.h"
+#include <fstream>
#include <mpg123.h>
-class DecoderMpg123 : public DecoderBase {
+class DecoderMpg123 : public Decoder {
private:
mpg123_handle *handle;
+ std::ifstream ifile;
size_t decode(const uint8_t *input, size_t input_size, uint8_t *output, size_t output_size);
- protected:
- virtual size_t decode(ReadFunc read, uint8_t *output, size_t output_size);
-
public:
- DecoderMpg123();
+ DecoderMpg123(const std::string& filename);
~DecoderMpg123();
+
+ virtual std::size_t read(char* buf, std::size_t buf_size);
};
#endif
diff --git a/encoder.cpp b/encoder.cpp
index 0f2a5fe..9d352dc 100644
--- a/encoder.cpp
+++ b/encoder.cpp
@@ -6,18 +6,13 @@
#include <map>
-EncoderFilter::EncoderFilter(EncoderBase::p encoder_) {
- encoder = encoder_;
-}
-
-typedef boost::function<EncoderBase::p ()> EncoderFactory;
+typedef boost::function<Encoder::p (RawAudioSource::p)> EncoderFactory;
std::map<std::string, EncoderFactory> encoder_factories;
-void encoder::init() {
+void Encoder::init() {
encoder_factories["lame"] = boost::factory<boost::shared_ptr<EncoderLame> >();
}
-//! Construct a filter with the given encoder.
-EncoderFilter::p encoder::get_encoder(const std::string& name) {
- return EncoderFilter::p(new EncoderFilter(encoder_factories[name]()));
+Encoder::p Encoder::get(const std::string& name, RawAudioSource::p source) {
+ return encoder_factories[name](source);
}
diff --git a/encoder.h b/encoder.h
index d000ffc..6d7a0c1 100644
--- a/encoder.h
+++ b/encoder.h
@@ -1,57 +1,27 @@
#ifndef ENCODER_H
#define ENCODER_H
-#include <boost/iostreams/concepts.hpp>
-#include <boost/iostreams/operations.hpp>
+#include "decoder.h"
+
#include <boost/shared_ptr.hpp>
-#include <boost/function.hpp>
-#include <iostream>
#include <string>
-class EncoderBase {
- friend class EncoderFilter;
-
- protected:
- typedef boost::function<std::size_t (char*, std::size_t)> ReadFunc;
+class Encoder {
+ public:
+ typedef boost::shared_ptr<Encoder> p;
- virtual size_t encode(ReadFunc read, uint8_t *output, size_t output_size) = 0;
+ //! Virtual destructor.
+ virtual ~Encoder() {}
- public:
- typedef boost::shared_ptr<EncoderBase> p;
- virtual ~EncoderBase() {}
-};
-
-//! Input filter to hold an encoder in a filter chain.
-class EncoderFilter : public boost::iostreams::multichar_input_filter {
- private:
- EncoderBase::p encoder;
+ //! Initialize encoders.
+ static void init();
- //! Functor binding a source to a read function.
- template<class T>
- struct ReadFunc {
- T& s;
-
- ReadFunc(T& s_) : s(s_) {}
-
- std::size_t operator()(char* buf, std::size_t buf_size) {
- return boost::iostreams::read(s, buf, buf_size);
- }
- };
-
- public:
- typedef boost::shared_ptr<EncoderFilter> p;
- EncoderFilter(EncoderBase::p encoder_);
+ //! Construct and return requested encoder.
+ static p get(const std::string& name, RawAudioSource::p source);
- template<typename Source>
- std::streamsize read(Source& src, char *s, std::streamsize n) {
- return encoder->encode(ReadFunc<Source>(src), (uint8_t*)s, n);
- };
-};
-
-namespace encoder {
- void init();
- EncoderFilter::p get_encoder(const std::string& name);
+ //! Read into provided buffer.
+ virtual std::size_t read(char* buf, std::size_t buf_size) = 0;
};
#endif
diff --git a/encoders/lame_encoder.cpp b/encoders/lame_encoder.cpp
index 7bf2ebc..be6f684 100644
--- a/encoders/lame_encoder.cpp
+++ b/encoders/lame_encoder.cpp
@@ -2,7 +2,7 @@
#include <stdexcept>
-EncoderLame::EncoderLame() {
+EncoderLame::EncoderLame(RawAudioSource::p source_) : source(source_) {
gfp = lame_init();
int error = lame_init_params(gfp);
@@ -23,15 +23,15 @@ size_t EncoderLame::flush(uint8_t *output, size_t output_size) {
return lame_encode_flush(gfp, output, output_size);
}
-size_t EncoderLame::encode(ReadFunc read, uint8_t *output, size_t output_size) {
+std::size_t EncoderLame::read(char* buf, std::size_t buf_size) {
char src_data[0x2000];
- std::streamsize src_read = read(src_data, 0x2000);
+ std::streamsize src_read = source->read(src_data, 0x2000);
if(src_read < 0)
src_read = 0;
- std::streamsize size = encode((const uint8_t*)src_data, src_read, (uint8_t*)output, output_size);
+ std::streamsize size = encode((const uint8_t*)src_data, src_read, (uint8_t*)buf, buf_size);
// no more data, flush encoder
if(src_read == 0 && size == 0) {
- size = flush((uint8_t*)output, output_size);
+ size = flush((uint8_t*)buf, buf_size);
}
return size;
diff --git a/encoders/lame_encoder.h b/encoders/lame_encoder.h
index 98ebc9f..3d1137d 100644
--- a/encoders/lame_encoder.h
+++ b/encoders/lame_encoder.h
@@ -5,19 +5,19 @@
#include <lame/lame.h>
-class EncoderLame : public EncoderBase {
+class EncoderLame : public Encoder {
private:
lame_global_flags *gfp;
+ RawAudioSource::p source;
size_t encode(const uint8_t *input, size_t input_size, uint8_t *output, size_t output_size);
size_t flush(uint8_t *output, size_t output_size);
- protected:
- virtual size_t encode(ReadFunc read, uint8_t *output, size_t output_size);
-
public:
- EncoderLame();
+ EncoderLame(RawAudioSource::p source_);
~EncoderLame();
+
+ virtual std::size_t read(char* buf, std::size_t buf_size);
};
#endif
diff --git a/main.cpp b/main.cpp
index 1099960..7f836cf 100644
--- a/main.cpp
+++ b/main.cpp
@@ -25,8 +25,8 @@ int main(int argc, char **argv) {
try {
config::init();
music::init(config::vm["audist.music_root"].as<std::string>());
- decoder::init();
- encoder::init();
+ Decoder::init();
+ Encoder::init();
boost::asio::io_service io_service;
diff --git a/music.cpp b/music.cpp
index 3e0ac14..3faa10b 100644
--- a/music.cpp
+++ b/music.cpp
@@ -1,7 +1,6 @@
#include "music.h"
#include "decoder.h"
#include "encoder.h"
-#include "transcode.h"
#include "tag.h"
#include "config.h"
@@ -238,10 +237,18 @@ void MusicTrack::render(HTTP::Connection::p req) {
req->add_header("content-type", "application/octet-stream");
if(req->args.count("decoder") && req->args.count("encoder")) {
- DecoderFilter::p d = decoder::get_decoder(req->args["decoder"]);
- EncoderFilter::p e = encoder::get_encoder(req->args["encoder"]);
- Transcoder t(path.string(), req, d, e);
- t.run();
+ Decoder::p decoder = Decoder::get(req->args["decoder"], path.string());
+ Encoder::p encoder = Encoder::get(req->args["encoder"], decoder);
+
+ // TODO: Make an encoder-to-istream adapter to get rid of this:
+ char data[0x1000];
+ std::streamsize size = 1;
+ while(size) {
+ size = encoder->read(data, 0x1000);
+ if(size > 0)
+ req->send_data(data, size);
+ }
+
} else {
fs::ifstream is(path, std::ios::in | std::ios::binary);
is.seekg(0, std::ios::end);
diff --git a/transcode.cpp b/transcode.cpp
deleted file mode 100644
index 394f604..0000000
--- a/transcode.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#include "transcode.h"
-
-#include <boost/iostreams/device/file.hpp>
-#include <boost/iostreams/filtering_stream.hpp>
-
-Transcoder::Transcoder(std::string p, HTTP::Connection::p r, DecoderFilter::p d, EncoderFilter::p e) : path(p), res(r), decoder(d), encoder(e) {
-}
-
-void Transcoder::run() {
- const std::streamsize buffer_size = 0x1000;
- boost::iostreams::file_source is(path, std::ios::in | std::ios::binary);
- boost::iostreams::filtering_istream s;
- s.push(*encoder.get(), buffer_size);
- s.push(*decoder.get(), buffer_size);
- s.push(is, buffer_size);
-
- res->send_data(s);
-}
diff --git a/transcode.h b/transcode.h
deleted file mode 100644
index 56f16c1..0000000
--- a/transcode.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef TRANSCODE_H
-#define TRANSCODE_H
-
-#include "decoder.h"
-#include "encoder.h"
-#include "http_connection.h"
-
-#include <string>
-
-class Transcoder {
- private:
- std::string path;
- HTTP::Connection::p res;
- DecoderFilter::p decoder;
- EncoderFilter::p encoder;
-
- public:
- Transcoder(std::string p, HTTP::Connection::p r, DecoderFilter::p d, EncoderFilter::p e);
- void run();
-};
-
-#endif