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