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
00297 PBoolean active;
00298 PBoolean first;
00299 unsigned channelNumber;
00300
00301 OpalAudioMixerStream();
00302 void WriteFrame(const StreamFrame & frame);
00303 void FillSilence(StreamFrame & retFrame, PINDEX ms);
00304 void PopFrame(StreamFrame & retFrame, PINDEX ms);
00305 PBoolean ReadFrame(StreamFrame & retFrame, PINDEX ms);
00306 };
00307
00309
00310
00311
00312
00313
00314 class OpalAudioMixer
00315 {
00316 public:
00317 typedef std::string Key_T;
00318 typedef std::map<Key_T, OpalAudioMixerStream *> StreamInfoMap_T;
00319 typedef std::map<Key_T, OpalAudioMixerStream::StreamFrame> MixerPCMMap_T;
00320
00321 class MixerFrame
00322 {
00323 protected:
00324 MixerPCMMap_T channelData;
00325
00326 PINDEX frameLengthSamples;
00327 mutable PIntArray mixedData;
00328 mutable PMutex mutex;
00329
00330 public:
00331 MixerFrame(PINDEX _frameLength);
00332 void CreateMixedData() const;
00333 PBoolean GetMixedFrame(OpalAudioMixerStream::StreamFrame & frame) const;
00334 PBoolean GetStereoFrame(OpalAudioMixerStream::StreamFrame & frame) const;
00335 PBoolean GetChannelFrame(Key_T key, OpalAudioMixerStream::StreamFrame & frame) const;
00336 void InsertFrame(Key_T key, OpalAudioMixerStream::StreamFrame & frame);
00337 };
00338
00339 protected:
00340 PINDEX frameLengthMs;
00341
00342 PMutex mutex;
00343 StreamInfoMap_T streamInfoMap;
00344 unsigned channelNumber;
00345
00346 PBoolean realTime;
00347 PBoolean pushThread;
00348 PThread * mixerWorkerThread;
00349 PBoolean threadRunning;
00350
00351 PBoolean audioStarted;
00352 PBoolean firstRead;
00353
00354 PTime timeOfNextRead;
00355 DWORD outputTimestamp;
00356
00357 public:
00358 OpalAudioMixer(PBoolean realTime = PTrue, PBoolean _pushThread = PTrue);
00359 virtual ~OpalAudioMixer() { }
00360 virtual PBoolean OnWriteAudio(const MixerFrame &);
00361 void AddStream(const Key_T & key, OpalAudioMixerStream * stream);
00362 void RemoveStream(const Key_T & key);
00363 void RemoveAllStreams();
00364 void StartThread();
00365 void ThreadMain();
00366 void ReadRoutine();
00367 void WriteMixedFrame();
00368 PBoolean Write(const Key_T & key, const RTP_DataFrame & rtp);
00369 };
00370
00371 #endif // OPAL_OPAL_OPAL_MIXER
00372