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