diff options
author | Jon Bergli Heier <snakebite@jvnv.net> | 2011-01-02 22:17:26 +0100 |
---|---|---|
committer | Jon Bergli Heier <snakebite@jvnv.net> | 2011-01-02 22:17:40 +0100 |
commit | 237c3e226b7c2ac391b0e8d354e5fc6f587a41ba (patch) | |
tree | e1f0c89792e2baccb1d1ed21b913445d6e330715 | |
parent | b72175dab679c14be80b6e5db7129f8d3b518079 (diff) |
Use a filtering_istream with custom filters to chain file -> decoder -> encoder.
-rw-r--r-- | decoder.h | 17 | ||||
-rw-r--r-- | encoder.h | 19 | ||||
-rw-r--r-- | encoders/lame_encoder.cpp | 8 | ||||
-rw-r--r-- | encoders/lame_encoder.h | 2 | ||||
-rw-r--r-- | music.cpp | 5 | ||||
-rw-r--r-- | transcode.cpp | 29 | ||||
-rw-r--r-- | transcode.h | 6 |
7 files changed, 61 insertions, 25 deletions
@@ -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); @@ -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); }; @@ -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(); }; |