diff --git a/client/decoder.h b/client/decoder.h index 4c797880..9f0ae236 100644 --- a/client/decoder.h +++ b/client/decoder.h @@ -2,7 +2,6 @@ #define DECODER_H #include "common/chunk.h" - class Decoder { public: diff --git a/server/encoder.h b/server/encoder.h index f4bef077..7565055d 100644 --- a/server/encoder.h +++ b/server/encoder.h @@ -1,13 +1,24 @@ #ifndef ENCODER_H #define ENCODER_H #include "common/chunk.h" +#include "common/sampleFormat.h" class Encoder { public: - Encoder(); + Encoder(const SampleFormat& format) : sampleFormat(format) + { + } + virtual double encode(Chunk* chunk) = 0; + virtual WireChunk* getHeader() + { + return NULL; + } + +protected: + SampleFormat sampleFormat; }; diff --git a/server/oggEncoder.cpp b/server/oggEncoder.cpp index 39fb006b..ad089700 100644 --- a/server/oggEncoder.cpp +++ b/server/oggEncoder.cpp @@ -5,21 +5,16 @@ using namespace std; -OggEncoder::OggEncoder() +OggEncoder::OggEncoder(const SampleFormat& format) : Encoder(format), headerChunk(NULL) { init(); lastGranulepos = -1; } -bool OggEncoder::getHeader(Chunk* chunk) +WireChunk* OggEncoder::getHeader() { - WireChunk* wireChunk = chunk->wireChunk; - wireChunk->type = chunk_type::header; - wireChunk->payload = (char*)realloc(wireChunk->payload, oggHeaderLen); - memcpy(wireChunk->payload, oggHeader, oggHeaderLen); - wireChunk->length = oggHeaderLen; - return true; + return headerChunk; } @@ -137,7 +132,7 @@ void OggEncoder::init() *********************************************************************/ - ret=vorbis_encode_init_vbr(&vi,2,48000,0.7); + ret=vorbis_encode_init_vbr(&vi, sampleFormat.channels, sampleFormat.rate, 0.9); /* do not continue if setup failed; this can happen if we ask for a mode that libVorbis does not support (eg, too low a bitrate, etc, @@ -176,21 +171,22 @@ void OggEncoder::init() */ // while(!eos){ size_t pos(0); - oggHeader = (char*)malloc(0); - oggHeaderLen = 0; + headerChunk = Chunk::makeChunk(chunk_type::header, 0); while (true) { int result=ogg_stream_flush(&os,&og); if (result == 0) break; - oggHeaderLen += og.header_len + og.body_len; - oggHeader = (char*)realloc(oggHeader, oggHeaderLen); + headerChunk->length += og.header_len + og.body_len; + headerChunk->payload = (char*)realloc(headerChunk->payload, headerChunk->length); cout << "HeadLen: " << og.header_len << ", bodyLen: " << og.body_len << ", result: " << result << "\n"; - memcpy(oggHeader + pos, og.header, og.header_len); + memcpy(headerChunk->payload + pos, og.header, og.header_len); pos += og.header_len; - memcpy(oggHeader + pos, og.body, og.body_len); + memcpy(headerChunk->payload + pos, og.body, og.body_len); pos += og.body_len; } + + // fwrite(og.header,1,og.header_len,stdout); // fwrite(og.body,1,og.body_len,stdout); // } diff --git a/server/oggEncoder.h b/server/oggEncoder.h index acfd9b27..b8e34808 100644 --- a/server/oggEncoder.h +++ b/server/oggEncoder.h @@ -4,12 +4,12 @@ #include -class OggEncoder +class OggEncoder : public Encoder { public: - OggEncoder(); + OggEncoder(const SampleFormat& format); virtual double encode(Chunk* chunk); - virtual bool getHeader(Chunk* chunk); + virtual WireChunk* getHeader(); private: void init(); @@ -31,11 +31,10 @@ private: ogg_packet header_code; ogg_int64_t lastGranulepos; + WireChunk* headerChunk; int eos=0,ret; int i, founddata; - char* oggHeader; - int oggHeaderLen; int32_t tv_sec; int32_t tv_usec; diff --git a/server/pcmEncoder.cpp b/server/pcmEncoder.cpp index f9746442..1947e938 100644 --- a/server/pcmEncoder.cpp +++ b/server/pcmEncoder.cpp @@ -1,6 +1,6 @@ #include "pcmEncoder.h" -PcmEncoder::PcmEncoder() +PcmEncoder::PcmEncoder(const SampleFormat& format) : Encoder(format) { } diff --git a/server/pcmEncoder.h b/server/pcmEncoder.h index 3d2406f1..157b0910 100644 --- a/server/pcmEncoder.h +++ b/server/pcmEncoder.h @@ -3,10 +3,10 @@ #include "encoder.h" -class PcmEncoder +class PcmEncoder : public Encoder { public: - PcmEncoder(); + PcmEncoder(const SampleFormat& format); virtual double encode(Chunk* chunk); }; diff --git a/server/snapServer.cpp b/server/snapServer.cpp index a0e76625..fe7a76d8 100644 --- a/server/snapServer.cpp +++ b/server/snapServer.cpp @@ -150,7 +150,8 @@ cout << "Sending header: " << headerChunk->wireChunk->length << "\n"; void setHeader(shared_ptr chunk) { - headerChunk = chunk; + if (chunk && (chunk->wireChunk != NULL)) + headerChunk = shared_ptr(chunk); } void send(shared_ptr chunk) @@ -220,13 +221,15 @@ int main(int argc, char* argv[]) size_t port; string fifoName; + string codec; bool runAsDaemon; po::options_description desc("Allowed options"); desc.add_options() ("help,h", "produce help message") ("port,p", po::value(&port)->default_value(98765), "port to listen on") - ("sampleformat,f", po::value(&sampleFormat)->default_value("48000:16:2"), "sample format") + ("sampleformat,s", po::value(&sampleFormat)->default_value("48000:16:2"), "sample format") + ("codec,c", po::value(&codec)->default_value("ogg"), "transport codec [ogg|pcm]") ("fifo,f", po::value(&fifoName)->default_value("/tmp/snapfifo"), "name of fifo file") ("daemon,d", po::bool_switch(&runAsDaemon)->default_value(false), "daemonize") ; @@ -276,9 +279,18 @@ int main(int argc, char* argv[]) size_t duration = 50; SampleFormat format(sampleFormat); - OggEncoder encoder; - shared_ptr header(new Chunk(format, Chunk::makeChunk(chunk_type::header, 0))); - encoder.getHeader(header.get()); + std::auto_ptr encoder; + if (codec == "ogg") + encoder.reset(new OggEncoder(sampleFormat)); + else if (codec == "pcm") + encoder.reset(new PcmEncoder(sampleFormat)); + else + { + cout << "unknown codec: " << codec << "\n"; + return 1; + } + + shared_ptr header(new Chunk(format, encoder->getHeader())); server->setHeader(header); while (!g_terminated) @@ -307,7 +319,7 @@ size_t duration = 50; wireChunk->tv_sec = tvChunk.tv_sec; wireChunk->tv_usec = tvChunk.tv_usec; - double chunkDuration = encoder.encode(chunk.get()); + double chunkDuration = encoder->encode(chunk.get()); if (chunkDuration > 0) server->send(chunk); //cout << wireChunk->tv_sec << ", " << wireChunk->tv_usec / 1000 << "\n";