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