summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Bergli Heier <snakebite@jvnv.net>2011-01-02 22:17:26 +0100
committerJon Bergli Heier <snakebite@jvnv.net>2011-01-02 22:17:40 +0100
commit237c3e226b7c2ac391b0e8d354e5fc6f587a41ba (patch)
treee1f0c89792e2baccb1d1ed21b913445d6e330715
parentb72175dab679c14be80b6e5db7129f8d3b518079 (diff)
Use a filtering_istream with custom filters to chain file -> decoder -> encoder.
-rw-r--r--decoder.h17
-rw-r--r--encoder.h19
-rw-r--r--encoders/lame_encoder.cpp8
-rw-r--r--encoders/lame_encoder.h2
-rw-r--r--music.cpp5
-rw-r--r--transcode.cpp29
-rw-r--r--transcode.h6
7 files changed, 61 insertions, 25 deletions
diff --git a/decoder.h b/decoder.h
index b4dcdb6..a7aaad9 100644
--- a/decoder.h
+++ b/decoder.h
@@ -5,6 +5,8 @@
#include <boost/function.hpp>
#include <boost/functional/factory.hpp>
#include <boost/functional/value_factory.hpp>
+#include <boost/iostreams/concepts.hpp>
+#include <boost/iostreams/operations.hpp>
#include <string>
@@ -13,6 +15,21 @@ class DecoderBase {
virtual size_t decode(const uint8_t *input, size_t input_size, uint8_t *output, size_t output_size) = 0;
};
+class DecoderFilter : public boost::iostreams::multichar_input_filter {
+ private:
+ DecoderBase& decoder;
+ public:
+ DecoderFilter(DecoderBase& decoder_) : decoder(decoder_) {};
+ template<typename Source>
+ std::streamsize read(Source& src, char *s, std::streamsize n) {
+ char src_data[0x2000];
+ std::streamsize src_read = boost::iostreams::read(src, src_data, 0x2000);
+ if(src_read < 0)
+ src_read = 0;
+ return decoder.decode((const uint8_t*)src_data, src_read, (uint8_t*)s, n);
+ };
+};
+
namespace decoder {
void init();
DecoderBase *get_decoder(const std::string& name);
diff --git a/encoder.h b/encoder.h
index 9949b52..7021cdc 100644
--- a/encoder.h
+++ b/encoder.h
@@ -5,15 +5,32 @@
#include <boost/function.hpp>
#include <boost/functional/factory.hpp>
#include <boost/functional/value_factory.hpp>
+#include <boost/iostreams/concepts.hpp>
+#include <boost/iostreams/operations.hpp>
#include <string>
class EncoderBase {
public:
- virtual size_t encode(uint8_t *input, size_t input_size, uint8_t *output, size_t output_size) = 0;
+ virtual size_t encode(const uint8_t *input, size_t input_size, uint8_t *output, size_t output_size) = 0;
virtual size_t flush(uint8_t *output, size_t output_size) = 0;
};
+class EncoderFilter : public boost::iostreams::multichar_input_filter {
+ private:
+ EncoderBase& encoder;
+ public:
+ EncoderFilter(EncoderBase& encoder_) : encoder(encoder_) {};
+ template<typename Source>
+ std::streamsize read(Source& src, char *s, std::streamsize n) {
+ char src_data[0x2000];
+ std::streamsize src_read = boost::iostreams::read(src, src_data, 0x2000);
+ if(src_read < 0)
+ src_read = 0;
+ return encoder.encode((const uint8_t*)src_data, src_read, (uint8_t*)s, n);
+ };
+};
+
namespace encoder {
void init();
EncoderBase *get_encoder(const std::string& name);
diff --git a/encoders/lame_encoder.cpp b/encoders/lame_encoder.cpp
index 4cbfc9c..125ee5e 100644
--- a/encoders/lame_encoder.cpp
+++ b/encoders/lame_encoder.cpp
@@ -15,12 +15,10 @@ EncoderLame::~EncoderLame() {
lame_close(gfp);
}
-size_t EncoderLame::encode(uint8_t *input, size_t input_size, uint8_t *output, size_t output_size) {
- size_t size = lame_encode_buffer_interleaved(gfp, (short*)input, input_size / 4, output, output_size);
- return size;
+size_t EncoderLame::encode(const uint8_t *input, size_t input_size, uint8_t *output, size_t output_size) {
+ return lame_encode_buffer_interleaved(gfp, (short*)input, input_size / 4, output, output_size);
}
size_t EncoderLame::flush(uint8_t *output, size_t output_size) {
- size_t size = lame_encode_flush(gfp, output, output_size);
- return size;
+ return lame_encode_flush(gfp, output, output_size);
}
diff --git a/encoders/lame_encoder.h b/encoders/lame_encoder.h
index 47f9666..1843361 100644
--- a/encoders/lame_encoder.h
+++ b/encoders/lame_encoder.h
@@ -12,7 +12,7 @@ class EncoderLame : public EncoderBase {
public:
EncoderLame();
~EncoderLame();
- size_t encode(uint8_t *input, size_t input_size, uint8_t *output, size_t output_size);
+ 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);
};
diff --git a/music.cpp b/music.cpp
index ec2f537..9892526 100644
--- a/music.cpp
+++ b/music.cpp
@@ -132,16 +132,15 @@ void MusicTrack::render(HTTP::Connection::p req, HTTPResponse& res) {
Tag *t = new ID3Tag(path.string());
delete t;
- fs::ifstream is(path, std::ios::binary | std::ios::in);
-
if(req->args.count("decoder") && req->args.count("encoder")) {
DecoderBase *d = decoder::get_decoder(req->args["decoder"]);
EncoderBase *e = encoder::get_encoder(req->args["encoder"]);
- Transcoder t(is, res, *d, *e);
+ Transcoder t(path.string(), res, *d, *e);
t.run();
delete d;
delete e;
} else {
+ fs::ifstream is(path, std::ios::in | std::ios::binary);
is.seekg(0, std::ios::end);
res.add_header("content-length", boost::str(boost::format("%d") % is.tellg()));
is.seekg(0, std::ios::beg);
diff --git a/transcode.cpp b/transcode.cpp
index 249ffb3..5244627 100644
--- a/transcode.cpp
+++ b/transcode.cpp
@@ -1,20 +1,25 @@
#include "transcode.h"
-Transcoder::Transcoder(std::istream& i, HTTPResponse& r, DecoderBase& d, EncoderBase& e) : is(i), res(r), decoder(d), encoder(e) {
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+
+Transcoder::Transcoder(std::string p, HTTPResponse& r, DecoderBase& d, EncoderBase& 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(EncoderFilter(encoder), buffer_size);
+ s.push(DecoderFilter(decoder), buffer_size);
+ s.push(is, buffer_size);
+
char data[0x1000];
- bool encoding_fone = false;
- while(!encoding_fone) {
- size_t decoded_size = 0;
- char decoded_data[0x1000];
- if(is.good()) {
- is.read(data, 0x1000);
- decoded_size = decoder.decode((uint8_t*)data, is.gcount(), (uint8_t*)decoded_data, 0x1000);
- }
- char encoded_data[0x1000];
- size_t encoded_size = encoder.encode((uint8_t*)decoded_data, decoded_size, (uint8_t*)encoded_data, 0x1000);
- res.write(encoded_data, encoded_size);
+ std::streamsize size = 1;
+ while(size) {
+ s.read(data, 0x1000);
+ size = s.gcount();
+ if(size > 0)
+ res.write(data, size);
}
}
diff --git a/transcode.h b/transcode.h
index 2a63b17..d0e781d 100644
--- a/transcode.h
+++ b/transcode.h
@@ -5,17 +5,17 @@
#include "encoder.h"
#include "http.h"
-#include <iostream>
+#include <string>
class Transcoder {
private:
- std::istream& is;
+ std::string path;
HTTPResponse& res;
DecoderBase& decoder;
EncoderBase& encoder;
public:
- Transcoder(std::istream& i, HTTPResponse& r, DecoderBase& d, EncoderBase& e);
+ Transcoder(std::string p, HTTPResponse& r, DecoderBase& d, EncoderBase& e);
void run();
};