00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef OPAL_OPAL_OPALMIXER_H
00034 #define OPAL_OPAL_OPALMIXER_H
00035
00036 #ifndef _PTLIB_H
00037 #include <ptlib.h>
00038 #endif
00039
00040 #include <opal/buildopts.h>
00041
00042 #include <queue>
00043
00044 #include <ptlib/psync.h>
00045 #include <ptclib/delaychan.h>
00046
00047 #include <rtp/rtp.h>
00048 #include <codec/opalwavfile.h>
00049
00050 template <typename Locker_T = PSyncNULL>
00051 class PMemBuffer
00052 {
00053 public:
00054 struct Common {
00055 Common(size_t size)
00056 : base(size)
00057 {
00058 refCount = 1;
00059 }
00060
00061 Common(BYTE * ptr, size_t size)
00062 : base(ptr, size)
00063 {
00064 refCount = 1;
00065 }
00066
00067 mutable int refCount;
00068 mutable Locker_T mutex;
00069 mutable PBYTEArray base;
00070 };
00071
00072 Common * common;
00073
00074 protected:
00075 BYTE * data;
00076 PINDEX dataLen;
00077
00078 public:
00079 PMemBuffer()
00080 {
00081 common = NULL;
00082 data = NULL;
00083 dataLen = 0;
00084 }
00085
00086 PMemBuffer(PINDEX size)
00087 {
00088 common = new Common(size);
00089 data = common->base.GetPointer();
00090 dataLen = size;
00091 }
00092
00093 PMemBuffer(BYTE * ptr, size_t size)
00094 {
00095 common = new Common(ptr, size);
00096 data = common->base.GetPointer();
00097 dataLen = size;
00098 }
00099
00100 PMemBuffer(const PBYTEArray & obj)
00101 {
00102 common = new Common(obj.GetPointer(), obj.GetSize());
00103 data = common->base.GetPointer();
00104 dataLen = obj.GetSize();
00105 }
00106
00107 PMemBuffer(const PMemBuffer & obj)
00108 {
00109 PWaitAndSignal m(obj.common->mutex);
00110 common = obj.common;
00111 ++common->refCount;
00112 data = obj.data;
00113 dataLen = obj.dataLen;
00114 }
00115
00116 ~PMemBuffer()
00117 {
00118 if (common != NULL) {
00119 common->mutex.Wait();
00120 PBoolean last = common->refCount == 1;
00121 if (last) {
00122 common->mutex.Signal();
00123 delete common;
00124 }
00125 else {
00126 --common->refCount;
00127 common->mutex.Signal();
00128 }
00129 common = NULL;
00130 data = NULL;
00131 dataLen = 0;
00132 }
00133 }
00134
00135 PMemBuffer & operator = (const PMemBuffer & obj)
00136 {
00137 if (&obj == this)
00138 return *this;
00139
00140 if (common != NULL) {
00141 common->mutex.Wait();
00142 PBoolean last = common->refCount == 1;
00143 if (last) {
00144 common->mutex.Signal();
00145 delete common;
00146 }
00147 else
00148 {
00149 --common->refCount;
00150 common->mutex.Signal();
00151 }
00152 common = NULL;
00153 data = NULL;
00154 dataLen = 0;
00155 }
00156 {
00157 PWaitAndSignal m(obj.common->mutex);
00158 common = obj.common;
00159 ++common->refCount;
00160 data = obj.data;
00161 dataLen = obj.dataLen;
00162 }
00163
00164 return *this;
00165 }
00166
00167 void MakeUnique()
00168 {
00169 PWaitAndSignal m(common->mutex);
00170 if (common->refCount == 1)
00171 return;
00172
00173 Common * newCommon = new Common(common->base.GetPointer(), common->base.GetSize());
00174 data = newCommon->base.GetPointer() + (data - common->base.GetPointer());
00175 --common->refCount;
00176 common = newCommon;
00177 }
00178
00179
00180
00181 void SetBase(PINDEX offs)
00182 {
00183 PWaitAndSignal m(common->mutex);
00184 data = common->base.GetPointer() + offs;
00185 if (offs + dataLen > common->base.GetSize())
00186 dataLen = common->base.GetSize() - offs;
00187 }
00188
00189
00190
00191 void Rebase(PINDEX offs)
00192 {
00193 PWaitAndSignal m(common->mutex);
00194 SetBase(offs + data - common->base.GetPointer());
00195 }
00196
00197
00198 void SetSize(PINDEX size)
00199 {
00200 if (common == NULL) {
00201 common = new Common(size);
00202 data = common->base.GetPointer();
00203 dataLen = size;
00204 }
00205 else {
00206 PWaitAndSignal m(common->mutex);
00207 if (size < dataLen)
00208 dataLen = size;
00209 else {
00210 PINDEX offs = data - common->base.GetPointer();
00211 if (offs + size < common->base.GetSize())
00212 dataLen = size;
00213 else
00214 dataLen = common->base.GetSize() - offs;
00215 }
00216 }
00217 }
00218
00219 BYTE * GetPointerAndLock()
00220 {
00221 PAssert(common != NULL, "NULL pointer");
00222 common->mutex.Wait();
00223 return data;
00224 }
00225
00226 inline const BYTE * GetPointerAndLock() const
00227 {
00228 PAssert(common != NULL, "NULL pointer");
00229 common->mutex.Wait();
00230 return data;
00231 }
00232
00233 inline PINDEX GetSize() const
00234 { return dataLen; }
00235
00236 inline void Lock() const
00237 {
00238 common->mutex.Wait();
00239 }
00240
00241 inline void Unlock() const
00242 {
00243 common->mutex.Signal();
00244 }
00245
00246 inline PSync & GetMutex()
00247 {
00248 return common->mutex;
00249 }
00250 };
00251
00253
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00272
00273
00274
00275
00276 class OpalAudioMixerStream {
00277 public:
00278 class StreamFrame : public PMemBuffer<PMutex> {
00279 public:
00280 DWORD timestamp;
00281 unsigned channelNumber;
00282
00283 StreamFrame()
00284 : timestamp(0)
00285 , channelNumber(0)
00286 { }
00287
00288 StreamFrame(const RTP_DataFrame & rtp);
00289 };
00290 typedef std::queue<StreamFrame> StreamFrameQueue_T;
00291
00292 PMutex mutex;
00293 StreamFrameQueue_T frameQueue;
00294 StreamFrame frameCache;
00295 DWORD cacheTimeStamp;
00296 DWORD writtenTimeStamp;
00297
00298 PBoolean active;
00299 PBoolean first;
00300 unsigned channelNumber;
00301
00302 OpalAudioMixerStream();
00303 void WriteFrame(const StreamFrame & frame);
00304 void FillSilence(StreamFrame & retFrame, PINDEX ms);
00305 void PopFrame(StreamFrame & retFrame, PINDEX ms);
00306 PBoolean ReadFrame(StreamFrame & retFrame, PINDEX ms);
00307 };
00308
00310
00311
00312
00313
00314
00315 class OpalAudioMixer
00316 {
00317 public:
00318 typedef std::string Key_T;
00319 typedef std::map<Key_T, OpalAudioMixerStream *> StreamInfoMap_T;
00320 typedef std::map<Key_T, OpalAudioMixerStream::StreamFrame> MixerPCMMap_T;
00321
00322 class MixerFrame
00323 {
00324 protected:
00325 MixerPCMMap_T channelData;
00326
00327 PINDEX frameLengthSamples;
00328 mutable PIntArray mixedData;
00329 mutable PMutex mutex;
00330
00331 public:
00332 MixerFrame(PINDEX _frameLength);
00333 void CreateMixedData() const;
00334 PBoolean GetMixedFrame(OpalAudioMixerStream::StreamFrame & frame) const;
00335 PBoolean GetStereoFrame(OpalAudioMixerStream::StreamFrame & frame) const;
00336 PBoolean GetChannelFrame(Key_T key, OpalAudioMixerStream::StreamFrame & frame) const;
00337 void InsertFrame(Key_T key, OpalAudioMixerStream::StreamFrame & frame);
00338 };
00339
00340 protected:
00341 PINDEX frameLengthMs;
00342
00343 PMutex mutex;
00344 StreamInfoMap_T streamInfoMap;
00345 unsigned channelNumber;
00346
00347 PBoolean realTime;
00348 PBoolean pushThread;
00349 PThread * mixerWorkerThread;
00350 PBoolean threadRunning;
00351
00352 PBoolean audioStarted;
00353 PBoolean firstRead;
00354
00355 PTime timeOfNextRead;
00356 DWORD outputTimestamp;
00357
00358 public:
00359 OpalAudioMixer(PBoolean realTime = PTrue, PBoolean _pushThread = PTrue);
00360 virtual ~OpalAudioMixer() { }
00361 virtual PBoolean OnWriteAudio(const MixerFrame &);
00362 void AddStream(const Key_T & key, OpalAudioMixerStream * stream);
00363 void RemoveStream(const Key_T & key);
00364 void RemoveAllStreams();
00365 void StartThread();
00366 void ThreadMain();
00367 void ReadRoutine();
00368 void WriteMixedFrame();
00369 PBoolean Write(const Key_T & key, const RTP_DataFrame & rtp);
00370 };
00371
00372 #endif // OPAL_OPAL_OPAL_MIXER
00373