diff --git a/darkice/trunk/src/BufferedSink.cpp b/darkice/trunk/src/BufferedSink.cpp index bcbc4b1..cb1c77f 100644 --- a/darkice/trunk/src/BufferedSink.cpp +++ b/darkice/trunk/src/BufferedSink.cpp @@ -89,18 +89,24 @@ static const char fileid[] = "$Id$"; *----------------------------------------------------------------------------*/ void BufferedSink :: init ( Sink * sink, - unsigned int size ) throw ( Exception ) + unsigned int size, + unsigned int chunkSize ) throw ( Exception ) { if ( !sink ) { throw Exception( __FILE__, __LINE__, "no sink"); } - this->sink = sink; // create a reference - this->bufferSize = size; - this->buffer = new unsigned char[bufferSize]; - this->bufferEnd = buffer + bufferSize; - this->inp = buffer; - this->outp = buffer; + this->sink = sink; // create a reference + this->chunkSize = chunkSize ? chunkSize : 1; + this->bufferSize = size; + // make bufferSize a multiple of chunkSize + this->bufferSize -= this->bufferSize % this->chunkSize; + this->peak = 0; + this->misalignment = 0; + this->buffer = new unsigned char[bufferSize]; + this->bufferEnd = buffer + bufferSize; + this->inp = buffer; + this->outp = buffer; } @@ -110,8 +116,10 @@ BufferedSink :: init ( Sink * sink, BufferedSink :: BufferedSink ( const BufferedSink & buffer ) throw ( Exception ) { - init( buffer.sink.get(), buffer.bufferSize); + init( buffer.sink.get(), buffer.bufferSize, buffer.chunkSize); + this->peak = buffer.peak; + this->misalignment = buffer.misalignment; memcpy( this->buffer, buffer.buffer, this->bufferSize); } @@ -141,8 +149,10 @@ BufferedSink :: operator= ( const BufferedSink & buffer ) if ( this != &buffer ) { strip(); Sink::operator=( buffer ); - init( buffer.sink.get(), buffer.bufferSize); + init( buffer.sink.get(), buffer.bufferSize, buffer.chunkSize); + this->peak = buffer.peak; + this->misalignment = buffer.misalignment; memcpy( this->buffer, buffer.buffer, this->bufferSize); } @@ -155,6 +165,8 @@ BufferedSink :: operator= ( const BufferedSink & buffer ) * All data is consumed. The return value is less then bufferSize only * if the BufferedSink's internal buffer is smaller than bufferSize, * thus can't hold that much + * The data to be stored is treated as parts with chunkSize size + * Only full chunkSize sized parts are stored *----------------------------------------------------------------------------*/ unsigned int BufferedSink :: store ( const void * buffer, @@ -176,49 +188,71 @@ BufferedSink :: store ( const void * buffer, oldInp = inp; buf = (const unsigned char *) buffer; - /* cut the front of the supplied buffer if it wouldn't fit */ + // adjust so it is a multiple of chunkSize + bufferSize -= bufferSize % chunkSize; + + // cut the front of the supplied buffer if it wouldn't fit if ( bufferSize > this->bufferSize ) { - size = this->bufferSize - 1; - buf += bufferSize - size; + size = this->bufferSize - 1; + size -= size % chunkSize; // keep it a multiple of chunkSize + buf += bufferSize - size; } else { size = bufferSize; } - /* copy the data into the buffer */ + // copy the data into the buffer i = bufferEnd - inp; + if ( (i % chunkSize) != 0 ) { + throw Exception( __FILE__, __LINE__, "copy quantity not aligned", i); + } + if ( size <= i ) { - /* the place between inp and bufferEnd is - * big enough to hold the data */ + // the place between inp and bufferEnd is + // big enough to hold the data memcpy( inp, buf, size); inp = slidePointer( inp, size); - /* adjust outp, lose the data that was overwritten, if any */ + // adjust outp, lose the data that was overwritten, if any if ( outp > oldInp && outp <= inp ) { - outp = slidePointer( inp, 1); + outp = slidePointer( inp, chunkSize); } } else { - /* the place between inp and bufferEnd is not - * big enough to hold the data - * writing will take place in two turns, once from - * inp -> bufferEnd, then from buffer -> */ + // the place between inp and bufferEnd is not + // big enough to hold the data + // writing will take place in two turns, once from + // inp -> bufferEnd, then from buffer -> memcpy( inp, buf, i); i = size - i; + if ( (i % chunkSize) != 0 ) { + throw Exception(__FILE__, __LINE__, "copy quantity not aligned", i); + } memcpy( this->buffer, buf, i); inp = slidePointer( this->buffer, i); - /* adjust outp, lose the data that was overwritten, if any */ + // adjust outp, lose the data that was overwritten, if any if ( outp <= oldInp ) { if ( outp < inp ) { - outp = slidePointer( inp, 1); + outp = slidePointer( inp, chunkSize); } } else { - outp = slidePointer( inp, 1); + outp = slidePointer( inp, chunkSize); } } + updatePeak(); + + if ( ((inp - this->buffer) % chunkSize) != 0 ) { + throw Exception( __FILE__, __LINE__, + "inp not aligned", inp - this->buffer); + } + if ( ((outp - this->buffer) % chunkSize) != 0 ) { + throw Exception( __FILE__, __LINE__, + "outp not aligned", outp - this->buffer); + } + return size; } @@ -232,7 +266,9 @@ BufferedSink :: write ( const void * buf, unsigned int len ) throw ( Exception ) { unsigned int length; - + unsigned int soFar; + unsigned char * b = (unsigned char *) buf; + if ( !buf ) { throw Exception( __FILE__, __LINE__, "buf is null"); } @@ -241,43 +277,84 @@ BufferedSink :: write ( const void * buf, return 0; } - /* try to write data from the buffer first, if any */ + if ( !align() ) { + return 0; + } + + // make it a multiple of chunkSize + len -= len % chunkSize; + + // try to write data from the buffer first, if any if ( inp != outp ) { - unsigned int size; + unsigned int size = 0; + unsigned int total = 0; if ( outp > inp ) { - /* valuable data is between outp -> bufferEnd and buffer -> inp - * try to write the outp -> bufferEnd - * the rest will be written in the next if */ + // valuable data is between outp -> bufferEnd and buffer -> inp + // try to write the outp -> bufferEnd + // the rest will be written in the next if - size = bufferEnd - outp; - length = sink->write( outp, size); - outp = slidePointer( outp, length); + size = bufferEnd - outp - 1; + size -= size % chunkSize; + soFar = 0; + + while ( outp > inp && soFar < size && sink->canWrite( 0, 0) ) { + length = sink->write( outp + soFar, size - soFar); + outp = slidePointer( outp, length); + soFar += length; + } + + total += soFar; } if ( outp < inp ) { - /* valuable data is between outp and inp - * if the previous if wrote all data from the end - * this part will write the rest */ - + // valuable data is between outp and inp + // if the previous if wrote all data from the end + // this part will write the rest + size = inp - outp; - length = sink->write( outp, size); - outp = slidePointer( outp, length); + soFar = 0; + + while ( soFar < size && sink->canWrite( 0, 0) ) { + length = sink->write( outp + soFar, size - soFar); + outp = slidePointer( outp, length); + soFar += length; + } + + total += soFar; } + + while ( (outp - buffer) % chunkSize ) { + slidePointer( outp, 1); + } + + // calulate the misalignment to chunkSize boundaries + misalignment = (chunkSize - (total % chunkSize)) % chunkSize; } - /* the internal buffer is empty, try to write the fresh data */ - length = inp == outp ? sink->write( buf, len) : 0; + if ( !align() ) { + return 0; + } + + // the internal buffer is empty, try to write the fresh data + soFar = 0; + if ( inp != outp ) { + while ( soFar < len && sink->canWrite( 0, 0) ) { + soFar += sink->write( b + soFar, len - soFar); + } + } + length = soFar; + + // calulate the misalignment to chunkSize boundaries + misalignment = (chunkSize - (length % chunkSize)) % chunkSize; if ( length < len ) { - /* if not all fresh could be written, store the remains */ - - unsigned char * b = (unsigned char *) buf; + // if not all fresh could be written, store the remains store( b + length, len - length); } - /* tell them we ate everything */ + // tell them we ate everything up to chunkSize alignment return len; } @@ -303,6 +380,9 @@ BufferedSink :: close ( void ) throw ( Exception ) $Source$ $Log$ + Revision 1.3 2000/11/10 20:16:21 darkeye + first real tests with multiple streaming + Revision 1.2 2000/11/05 14:08:27 darkeye changed builting to an automake / autoconf environment diff --git a/darkice/trunk/src/BufferedSink.h b/darkice/trunk/src/BufferedSink.h index b06a27e..543e19b 100644 --- a/darkice/trunk/src/BufferedSink.h +++ b/darkice/trunk/src/BufferedSink.h @@ -66,6 +66,10 @@ class BufferedSink : public Sink unsigned char * buffer; unsigned char * bufferEnd; unsigned int bufferSize; + unsigned int peak; + + unsigned int chunkSize; + unsigned int misalignment; unsigned char * inp; unsigned char * outp; @@ -76,11 +80,12 @@ class BufferedSink : public Sink void init ( Sink * sink, - unsigned int size ) throw ( Exception ); + unsigned int size, + unsigned int chunkSize ) throw ( Exception ); void - strip ( void ) throw ( Exception ); + strip ( void ) throw ( Exception ); inline unsigned char * @@ -95,7 +100,42 @@ class BufferedSink : public Sink return p; } - + + + inline void + updatePeak ( void ) + { + unsigned int u; + + u = outp <= inp ? inp - outp : (bufferEnd - outp) + (inp - buffer); + if ( peak < u ) { + peak = u; + } + } + + + inline bool + align ( void ) + { + char b[] = { 0 }; + + while ( misalignment ) { + if ( sink->canWrite( 0, 0) ) { + unsigned int ret; + + if ( !(ret = sink->write( b, 1)) ) { + return false; + } + --misalignment; + + } else { + return false; + } + } + + return true; + } + protected: @@ -122,9 +162,10 @@ class BufferedSink : public Sink inline BufferedSink ( Sink * sink, - unsigned int size ) throw ( Exception ) + unsigned int size, + unsigned int chunkSize = 1 ) throw ( Exception ) { - init( sink, size); + init( sink, size, chunkSize); } @@ -142,6 +183,13 @@ class BufferedSink : public Sink operator= ( const BufferedSink & bs ) throw ( Exception ); + inline unsigned int + getPeak ( void ) const throw () + { + return peak; + } + + inline virtual bool open ( void ) throw ( Exception ) { @@ -198,6 +246,9 @@ class BufferedSink : public Sink $Source$ $Log$ + Revision 1.3 2000/11/10 20:16:21 darkeye + first real tests with multiple streaming + Revision 1.2 2000/11/05 17:37:24 darkeye removed clone() functions diff --git a/darkice/trunk/src/DarkIce.cpp b/darkice/trunk/src/DarkIce.cpp index d2f44a3..e0ebc87 100644 --- a/darkice/trunk/src/DarkIce.cpp +++ b/darkice/trunk/src/DarkIce.cpp @@ -38,12 +38,6 @@ #include "configure.h" #endif -#ifdef HAVE_UNISTD_H -#include -#else -#error need unistd.h -#endif - #ifdef HAVE_STDLIB_H #include #else @@ -153,9 +147,13 @@ DarkIce :: DarkIce ( int argc, void DarkIce :: init ( const Config & config ) throw ( Exception ) { + unsigned int bufferSecs; const ConfigSection * cs; const char * str; - unsigned int u, v, w; + unsigned int sampleRate; + unsigned int bitsPerSample; + unsigned int channel; + const char * device; int i; // the [general] section @@ -164,6 +162,8 @@ DarkIce :: init ( const Config & config ) throw ( Exception ) } str = cs->getForSure( "duration", " missing in section [general]"); duration = Util::strToL( str); + str = cs->getForSure( "bufferSecs", " missing in section [general]"); + bufferSecs = Util::strToL( str); // the [input] section @@ -172,17 +172,17 @@ DarkIce :: init ( const Config & config ) throw ( Exception ) } str = cs->getForSure( "sampleRate", " missing in section [input]"); - u = Util::strToL( str); - + sampleRate = Util::strToL( str); str = cs->getForSure( "bitsPerSample", " missing in section [input]"); - v = Util::strToL( str); - + bitsPerSample = Util::strToL( str); str = cs->getForSure( "channel", " missing in section [input]"); - w = Util::strToL( str); + channel = Util::strToL( str); + device = cs->getForSure( "device", " missing in section [input]"); - str = cs->getForSure( "device", " missing in section [input]"); - - dsp = new OssDspSource( str, u, v, w); + dsp = new OssDspSource( device, + sampleRate, + bitsPerSample, + channel ); encConnector = new Connector( dsp.get()); @@ -202,17 +202,20 @@ DarkIce :: init ( const Config & config ) throw ( Exception ) break; } - const char * encoder = 0; - unsigned int bitrate = 0; - const char * server = 0; - unsigned int port = 0; - const char * password = 0; - const char * mountPoint = 0; - const char * name = 0; - const char * description = 0; - const char * url = 0; - const char * genre = 0; - bool isPublic = false; + const char * encoder = 0; + unsigned int bitrate = 0; + const char * server = 0; + unsigned int port = 0; + const char * password = 0; + const char * mountPoint = 0; + const char * remoteDumpFile = 0; + const char * name = 0; + const char * description = 0; + const char * url = 0; + const char * genre = 0; + bool isPublic = false; + unsigned int lowpass = 0; + unsigned int highpass = 0; encoder = cs->getForSure( "encoder", " missing in section ", lame); str = cs->getForSure( "bitrate", " missing in section ", lame); @@ -222,12 +225,17 @@ DarkIce :: init ( const Config & config ) throw ( Exception ) port = Util::strToL( str); password = cs->getForSure( "password", " missing in section ", lame); mountPoint = cs->getForSure( "mountPoint"," missing in section ",lame); + remoteDumpFile = cs->get( "remoteDumpFile"); name = cs->getForSure( "name", " missing in section ", lame); description = cs->getForSure("description"," missing in section ",lame); url = cs->getForSure( "url", " missing in section ", lame); genre = cs->getForSure( "genre", " missing in section ", lame); str = cs->getForSure( "public", " missing in section ", lame); isPublic = Util::strEq( str, "yes") ? true : false; + str = cs->get( "lowpass"); + lowpass = str ? Util::strToL( str) : 0; + str = cs->get( "highpass"); + highpass = str ? Util::strToL( str) : 0; // generate the pipe names char pipeOutName[lameLen + pipeOutExtLen + 1]; @@ -240,6 +248,8 @@ DarkIce :: init ( const Config & config ) throw ( Exception ) // go on and create the things + outputs[i].pid = 0; + // the pipes outputs[i].encOutPipe = new PipeSource( pipeOutName); outputs[i].encInPipe = new PipeSink( pipeInName); @@ -262,26 +272,32 @@ DarkIce :: init ( const Config & config ) throw ( Exception ) // encoder related stuff outputs[i].encIn = new BufferedSink( outputs[i].encInPipe.get(), - 64 * 1024); + bufferSecs * (bitsPerSample / 8) * channel * sampleRate, + (bitsPerSample / 8) * channel ); encConnector->attach( outputs[i].encIn.get()); outputs[i].encoder = new LameEncoder( encoder, outputs[i].encInPipe->getFileName(), dsp.get(), outputs[i].encOutPipe->getFileName(), - bitrate ); + bitrate, + sampleRate, + channel, + lowpass, + highpass ); // streaming related stuff outputs[i].socket = new TcpSocket( server, port); outputs[i].ice = new IceCast( outputs[i].socket.get(), - password, - mountPoint, - name, - description, - url, - genre, - bitrate, - isPublic ); + password, + mountPoint, + remoteDumpFile, + name, + description, + url, + genre, + bitrate, + isPublic ); outputs[i].shoutConnector = new Connector( outputs[i].encOutPipe.get(), outputs[i].ice.get()); } @@ -350,7 +366,7 @@ DarkIce :: shout ( unsigned int ix ) throw ( Exception ) * (1024 / 8) * duration, 4096, - 1, + 10, 0 ); cout << len << " bytes transfered" << endl; @@ -367,37 +383,40 @@ DarkIce :: shout ( unsigned int ix ) throw ( Exception ) int DarkIce :: run ( void ) throw ( Exception ) { - pid_t pid; + int i; cout << "DarkIce" << endl << endl << flush; - pid = fork(); + for ( i = 0; i < noOutputs; ++i ) { + outputs[i].pid = fork(); - if ( pid == -1 ) { - throw Exception( __FILE__, __LINE__, "fork error", errno); - - } else if ( pid == 0 ) { - // this is the child - int i; + if ( outputs[i].pid == -1 ) { + throw Exception( __FILE__, __LINE__, "fork error", errno); + + } else if ( outputs[i].pid == 0 ) { + // this is the child - sleep ( 2 ); + sleep ( 1 ); - cout << "shouting" << endl << flush; - for ( i = 0; i < noOutputs; ++i ) { + cout << "shouting " << i << endl << flush; shout( i); - } - cout << "shouting ends" << endl << flush; + cout << "shouting ends " << i << endl << flush; - exit(0); - } else { - // this is the parent + exit(0); + } + } + + // this is the parent + + cout << "encoding" << endl << flush; + encode(); + cout << "encoding ends" << endl << flush; + + for ( i = 0; i < noOutputs; ++i ) { int status; - cout << "encoding" << endl << flush; - encode(); - cout << "encoding ends" << endl << flush; + waitpid( outputs[i].pid, &status, 0); - waitpid( pid, &status, 0); if ( !WIFEXITED(status) ) { throw Exception( __FILE__, __LINE__, "child exited abnormally", WEXITSTATUS(status)); @@ -413,6 +432,9 @@ DarkIce :: run ( void ) throw ( Exception ) $Source$ $Log$ + Revision 1.5 2000/11/10 20:16:21 darkeye + first real tests with multiple streaming + Revision 1.4 2000/11/09 22:09:46 darkeye added multiple outputs added configuration reading diff --git a/darkice/trunk/src/DarkIce.h b/darkice/trunk/src/DarkIce.h index 822ff26..05e8248 100644 --- a/darkice/trunk/src/DarkIce.h +++ b/darkice/trunk/src/DarkIce.h @@ -41,6 +41,16 @@ /* ============================================================ include files */ +#ifdef HAVE_CONFIG_H +#include "configure.h" +#endif + +#ifdef HAVE_UNISTD_H +#include +#else +#error need unistd.h +#endif + #include #include "Referable.h" @@ -82,6 +92,7 @@ class DarkIce : public virtual Referable Ref socket; Ref ice; Ref shoutConnector; + pid_t pid; } Output; @@ -164,6 +175,9 @@ class DarkIce : public virtual Referable $Source$ $Log$ + Revision 1.3 2000/11/10 20:16:21 darkeye + first real tests with multiple streaming + Revision 1.2 2000/11/09 22:09:46 darkeye added multiple outputs added configuration reading