1 /*
2  * opalmixer.h
3  *
4  * OPAL media mixers
5  *
6  * Open Phone Abstraction Library (OPAL)
7  * Formally known as the Open H323 project.
8  *
9  * Copyright (C) 2007 Post Increment
10  *
11  * The contents of this file are subject to the Mozilla Public License
12  * Version 1.0 (the "License"); you may not use this file except in
13  * compliance with the License. You may obtain a copy of the License at
14  * http://www.mozilla.org/MPL/
15  *
16  * Software distributed under the License is distributed on an "AS IS"
17  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
18  * the License for the specific language governing rights and limitations
19  * under the License.
20  *
21  * The Original Code is Open Phone Abstraction Library.
22  *
23  * The Initial Developer of the Original Code is Post Increment
24  *
25  * Contributor(s): Craig Southeren (craigs@postincrement.com)
26  *                 Robert Jongbloed (robertj@voxlucida.com.au)
27  *
28  * $Revision: 27149 $
29  * $Author: rjongbloed $
30  * $Date: 2012-03-07 18:32:36 -0600 (Wed, 07 Mar 2012) $
31  */
32 
33 
34 #ifndef OPAL_OPAL_OPALMIXER_H
35 #define OPAL_OPAL_OPALMIXER_H
36 
37 #ifndef _PTLIB_H
38 #include <ptlib.h>
39 #endif
40 
41 #include <opal/buildopts.h>
42 
43 #include <queue>
44 
45 #include <opal/localep.h>
46 #include <codec/vidcodec.h>
47 #include <ptclib/threadpool.h>
48 
49 
50 class RTP_DataFrame;
51 class OpalJitterBuffer;
52 class OpalMixerConnection;
53 
54 
55 //#define OPAL_MIXER_AUDIO_DEBUG 1
56 
57 
58 #define OPAL_OPT_LISTEN_ONLY "Listen-Only" ///< String option for listen only mixer connection
59 
60 
61 ///////////////////////////////////////////////////////////////////////////////
62 
63 /** Class base for a media mixer.
64 
65     The mixer operates by re-buffering the input media into chunks each with an
66     associated timestamp. A main mixer thread then reads from each  stream at
67     regular intervals, mixes the media and creates the output buffer.
68 
69     Note the timestamps of the input media are extremely important as they are
70     used so that breaks or too fast data in the input media is dealt with correctly.
71   */
72 class OpalBaseMixer
73 {
74   public:
75     OpalBaseMixer(
76       bool pushThread,    ///< Indicate if the push thread should be started
77       unsigned periodMS,  ///< The output buffer time in milliseconds
78       unsigned periodTS   ///< The output buffer time in RTP timestamp units
79     );
80 
81     virtual ~OpalBaseMixer();
82 
83     typedef PString Key_T;
84 
85     /**Add a stream to mixer using the specified key.
86       */
87     virtual bool AddStream(
88       const Key_T & key   ///< key for mixer stream
89     );
90 
91     /** Remove an input stream from mixer.
92       */
93     virtual void RemoveStream(
94       const Key_T & key   ///< key for mixer stream
95     );
96 
97     /** Remove all input streams from mixer.
98       */
99     virtual void RemoveAllStreams();
100 
101     /**Write an RTP data frame to mixer.
102        A copy of the RTP data frame is created. This function is generally
103        quite fast as the actual mixing is done in a different thread so
104        minimal interference with the normal media stream processing occurs.
105       */
106     virtual bool WriteStream(
107       const Key_T & key,          ///< key for mixer stream
108       const RTP_DataFrame & input ///< Input RTP data for media
109     );
110 
111     /**Read media from mixer.
112        A pull model system would call this function to get the mixed media
113        from the mixer. Note the stream indicated by the streamToIgnore key is
114        not included in the mixing operation, allowing for example, the member
115        of a conference to not hear themselves.
116 
117        Note this function is the function that does all the "heavy lifting"
118        for the mixer.
119       */
120     virtual RTP_DataFrame * ReadMixed();
121     virtual bool ReadMixed(RTP_DataFrame & mixed);
122 
123     /**Mixed data is now available.
124        For a push model system, this is called with mixed data as returned by
125        ReadMixed().
126 
127        The "mixed" parameter is a reference to a pointer, so if the consumer
128        wishes to take responsibility for deleting the pointer to an RTP data
129        frame, then they can set it to NULL.
130 
131        If false is returned then the push thread is exited.
132       */
133     virtual bool OnMixed(
134       RTP_DataFrame * & mixed   ///< Pointer to mixed media.
135     );
136 
137     /**Start the push thread.
138        Normally called internally.
139       */
140     void StartPushThread();
141 
142     /**Stop the push thread.
143        This will wait for th epush thread to terminate, so care must be taken
144        to avoid deadlocks when calling.
145       */
146     void StopPushThread(bool lock = true);
147 
148     /**Get the period for mixing in RTP timestamp units.
149       */
GetPeriodTS()150     unsigned GetPeriodTS() const { return m_periodTS; }
151 
152   protected:
153     struct Stream {
~StreamStream154       virtual ~Stream() { }
155       virtual void QueuePacket(const RTP_DataFrame & rtp) = 0;
156       queue<RTP_DataFrame> m_queue;
157     };
158     typedef std::map<Key_T, Stream *> StreamMap_T;
159 
160     virtual Stream * CreateStream() = 0;
161     virtual bool MixStreams(RTP_DataFrame & frame) = 0;
162     virtual size_t GetOutputSize() const = 0;
163 
164     virtual bool OnPush();
165     void PushThreadMain();
166 
167     bool      m_pushThread;      // true if to use a thread to push data out
168     unsigned  m_periodMS;        // Mixing interval in milliseconds
169     unsigned  m_periodTS;        // Mixing interval in timestamp units
170 
171     StreamMap_T     m_inputStreams;     // Map of key to stream for input RTP frame queues
172     unsigned        m_outputTimestamp;  // RTP timestamp for output data
173     RTP_DataFrame * m_pushFrame;        // Cached frame for pushing RTP
174     PThread *       m_workerThread;     // reader thread handle
175     bool            m_threadRunning;    // used to stop reader thread
176     PMutex          m_mutex;            // mutex for list of streams and thread handle
177 };
178 
179 ///////////////////////////////////////////////////////////////////////////////
180 
181 /** Class for an audio mixer.
182     This takes raw PCM-16 data and sums all the input data streams to produce
183     a single PCM-16 sample value.
184 
185     For 2 or less channels, they may be mixed as stereo where 16 bit PCM
186     samples are placed in adjacent pairs in the output, rather than summing
187     them.
188   */
189 class OpalAudioMixer : public OpalBaseMixer
190 {
191   public:
192     OpalAudioMixer(
193       bool stereo = false,    ///< Indicate stero or mixed mono mode
194       unsigned sampleRate = OpalMediaFormat::AudioClockRate, ///< Sample rate for audio, default 8kHz
195       bool pushThread = true, ///< Indicate push thread is to be used
196       unsigned period = 10    ///< Period for push/pull of audio from mixer in milliseconds
197     );
198 
~OpalAudioMixer()199     ~OpalAudioMixer() { StopPushThread(); }
200 
201     /** Remove an input stream from mixer.
202       */
203     virtual void RemoveStream(
204       const Key_T & key   ///< key for mixer stream
205     );
206 
207     /** Remove all input streams from mixer.
208       */
209     virtual void RemoveAllStreams();
210 
211     /**Return flag for mixing stereo audio data.
212       */
IsStereo()213     bool IsStereo() const { return m_stereo; }
214 
215     /**Get sample rate for audio.
216       */
GetSampleRate()217     unsigned GetSampleRate() const { return m_sampleRate; }
218 
219     /**Set sample rate for audio data.
220        Note that all streams must have the same sample rate.
221 
222        Returns false if attempts to set sample rate to something different to
223        existing streams.
224       */
225     bool SetSampleRate(
226       unsigned rate   ///< New rate
227     );
228 
229     /**Sets the size of the jitter buffer to be used by the specified stream
230        in this mixer. A mixer defaults to not having any jitter buffer enabled.
231 
232        If either jitter delay parameter is zero, it destroys the jitter buffer
233        attached to this mixer.
234       */
235     bool SetJitterBufferSize(
236       const Key_T & key,       ///< key for mixer stream
237       unsigned minJitterDelay, ///<  Minimum jitter buffer delay in RTP timestamp units
238       unsigned maxJitterDelay  ///<  Maximum jitter buffer delay in RTP timestamp units
239     );
240 
241   protected:
242     struct AudioStream : public Stream
243     {
244       AudioStream(OpalAudioMixer & mixer);
245       ~AudioStream();
246 
247       virtual void QueuePacket(const RTP_DataFrame & rtp);
248       const short * GetAudioDataPtr();
249 
250       OpalAudioMixer   & m_mixer;
251       OpalJitterBuffer * m_jitter;
252       unsigned           m_nextTimestamp;
253       PShortArray        m_cacheSamples;
254       size_t             m_samplesUsed;
255     };
256 
257     virtual Stream * CreateStream();
258     virtual bool MixStreams(RTP_DataFrame & frame);
259     virtual size_t GetOutputSize() const;
260 
261     void PreMixStreams();
262     void MixStereo(RTP_DataFrame & frame);
263     void MixAdditive(RTP_DataFrame & frame, const short * audioToSubtract);
264 
265   protected:
266     bool     m_stereo;
267     unsigned m_sampleRate;
268 
269     AudioStream    * m_left;
270     AudioStream    * m_right;
271     std::vector<int> m_mixedAudio;
272 };
273 
274 
275 ///////////////////////////////////////////////////////////////////////////////
276 
277 #if OPAL_VIDEO
278 
279 /**Video mixer.
280    This takes raw YUV420P frames with a PluginCodec_Video_FrameHeader in the
281    RTP data frames, scales them and places them in particular positions of the
282    output data frame. A number of different patterns for positioning the sub
283    images are available in the Styles enum.
284   */
285 class OpalVideoMixer : public OpalBaseMixer
286 {
287   public:
288     enum Styles {
289       eSideBySideLetterbox, /**< Two images side by side with black bars top and bottom.
290                                  It is expected that the input frames and output are all
291                                  the same aspect ratio, e.g. 4:3. Works well if inputs
292                                  are QCIF and output is CIF for example. */
293       eSideBySideScaled,    /**< Two images side by side, scaled to fit halves of output
294                                  frame. It is expected that the output frame be double
295                                  the width of the input data to maintain aspect ratio.
296                                  e.g. for CIF inputs, output would be 704x288. */
297       eStackedPillarbox,    /**< Two images, one on top of the other with black bars down
298                                  the sides. It is expected that the input frames and output
299                                  are all the same aspect ratio, e.g. 4:3. Works well if
300                                  inputs are QCIF and output is CIF for example. */
301       eStackedScaled,       /**< Two images, one on top of the other, scaled to fit halves
302                                  of output frame. It is expected that the output frame be
303                                  double the height of the input data to maintain aspect
304                                  ratio. e.g. for CIF inputs, output would be 352x576. */
305       eGrid,                /**< Standard 2x2, 3x3, 4x4 grid pattern. Size of grid is
306                                  dependent on the number of video streams. */
307     };
308 
309     OpalVideoMixer(
310       Styles style,           ///< Style for mixing video
311       unsigned width,         ///< Width of output frame
312       unsigned height,        ///< Height of output frame
313       unsigned rate = 15,     ///< Frames per second for output
314       bool pushThread = true  ///< A push thread is to be created
315     );
316 
~OpalVideoMixer()317     ~OpalVideoMixer() { StopPushThread(); }
318 
319     /**Get output video frame width.
320       */
GetFrameWidth()321     unsigned GetFrameWidth() const { return m_width; }
322 
323     /**Get output video frame height.
324       */
GetFrameHeight()325     unsigned GetFrameHeight() const { return m_height; }
326 
327     /**Get output video frame rate (frames per second)
328       */
GetFrameRate()329     unsigned GetFrameRate() const { return 1000/m_periodMS; }
330 
331     /**Set output video frame rate.
332        May be dynamically changed at any time.
333       */
334     bool SetFrameRate(
335       unsigned rate   // New frames per second.
336     );
337 
338     /**Set the output video frame width and height.
339        May be dynamically changed at any time.
340       */
341     bool SetFrameSize(
342       unsigned width,   ///< New width
343       unsigned height   ///< new height
344     );
345 
346   protected:
347     struct VideoStream : public Stream
348     {
349       VideoStream(OpalVideoMixer & mixer);
350       virtual void QueuePacket(const RTP_DataFrame & rtp);
351       void InsertVideoFrame(unsigned x, unsigned y, unsigned w, unsigned h);
352 
353       OpalVideoMixer & m_mixer;
354     };
355 
356     friend struct VideoStream;
357 
358     virtual Stream * CreateStream();
359     virtual bool MixStreams(RTP_DataFrame & frame);
360     virtual size_t GetOutputSize() const;
361 
362   protected:
363     Styles     m_style;
364     unsigned   m_width, m_height;
365     BYTE       m_bgFillRed,m_bgFillGreen,m_bgFillBlue;
366 
367     PBYTEArray m_frameStore;
368     size_t     m_lastStreamCount;
369 };
370 
371 #endif // OPAL_VIDEO
372 
373 
374 ///////////////////////////////////////////////////////////////////////////////
375 
376 
377 /**Base class for OpalMixerNode options.
378    The user may derive from this class, making sure they implement the Clone()
379    funciton, to add extra options for use by their OpalMixerNode derived class.
380   */
381 struct OpalMixerNodeInfo
382 {
383   OpalMixerNodeInfo(const char * name = NULL)
m_nameOpalMixerNodeInfo384     : m_name(name)
385     , m_listenOnly(false)
386     , m_sampleRate(OpalMediaFormat::AudioClockRate)
387 #if OPAL_VIDEO
388     , m_audioOnly(false)
389     , m_style(OpalVideoMixer::eGrid)
390     , m_width(PVideoFrameInfo::CIFWidth)
391     , m_height(PVideoFrameInfo::CIFHeight)
392     , m_rate(15)
393 #endif
394     , m_mediaPassThru(false)
395   { }
396 
~OpalMixerNodeInfoOpalMixerNodeInfo397   virtual ~OpalMixerNodeInfo() { }
398 
CloneOpalMixerNodeInfo399   virtual OpalMixerNodeInfo * Clone() const { return new OpalMixerNodeInfo(*this); }
400 
401   PString  m_name;                ///< Name for mixer node.
402   bool     m_listenOnly;          ///< Mixer only transmits data to "listeners"
403   unsigned m_sampleRate;          ///< Audio sample rate, usually 8000
404 #if OPAL_VIDEO
405   bool     m_audioOnly;           ///< No video is to be allowed.
406   OpalVideoMixer::Styles m_style; ///< Method for mixing video
407   unsigned m_width;               ///< Width of mixed video
408   unsigned m_height;              ///< Height of mixed video
409   unsigned m_rate;                ///< Frame rate of mixed video
410 #endif
411   bool     m_mediaPassThru;       /**< Enable media pass through to optimise mixer node
412                                        with precisely two attached connections. */
413 };
414 
415 
416 ///////////////////////////////////////////////////////////////////////////////
417 
418 class OpalMixerNode;
419 
420 
421 /** Mixer node manager.
422     This class is a collection of OpalMixerNodes.
423 	It provides access to nodes by GUID or name.
424   */
425 class OpalMixerNodeManager : public PObject
426 {
427     PCLASSINFO(OpalMixerNodeManager, PObject);
428   public:
429   /**@name Construction */
430   //@{
431     /**Create a new mixer node manager.
432      */
433     OpalMixerNodeManager();
434 
435     /**Destroy all mixer nodes.
436        Calls ShutDown.
437      */
438 	virtual ~OpalMixerNodeManager();
439 
440     /**Shuts down, removes and destroys all mixer nodes.
441       */
442     virtual void ShutDown();
443 
444     /** Execute garbage collection of nodes.
445         Returns true if all garbage has been collected.
446         Default behaviour deletes the objects that have been
447 		removed from the m_nodesByUID list.
448       */
449     virtual PBoolean GarbageCollection();
450   //@}
451 
452   /**@name Operations */
453   //@{
454     /**Create a new node.
455        This should create the new instance of the OpalMixerNode as required
456        by the derived class, if any.
457        The info variable should be created on the heap and it is subsequently
458        owned by the node. NULL can be passed if defaults are to be used.
459       */
460     virtual OpalMixerNode * CreateNode(
461       OpalMixerNodeInfo * info ///< Initial info for node
462     );
463 
464 	/**Add a new node.
465        The info variable should be created on the heap and it is subsequently
466        owned by the node. NULL can be passed if defaults are to be used.
467 	   Calls CreateNode.
468       */
469     virtual PSafePtr<OpalMixerNode> AddNode(
470       OpalMixerNodeInfo * info ///< Initial info for node
471     );
472 
473     /**Add an existing node.
474       */
475     void AddNode(OpalMixerNode * node);
476 
477     /**Get the first node.
478        The active nodes may be enumerated by the ++ operator on the PSafePtr.
479       */
480     PSafePtr<OpalMixerNode> GetFirstNode(
481       PSafetyMode mode = PSafeReference ///< Lock mode for returned pointer
482     ) const { return PSafePtr<OpalMixerNode>(m_nodesByUID, mode); }
483 
484     /**Find a new node.
485        This will search for the mixer node using GUID and then name.
486       */
487     virtual PSafePtr<OpalMixerNode> FindNode(
488       const PString & name,             ///< GUID or alias name for node
489       PSafetyMode mode = PSafeReference ///< Lock mode for returned pointer
490     );
491 
492     /**Remove a node.
493        Shut down all active connections with node, remove its name
494 	   associations and delete it.
495       */
496     virtual void RemoveNode(
497       OpalMixerNode & node
498     );
499 
500     /**Add node name to association list.
501       */
502     void AddNodeName(
503       PString name,        ///< alias name for node
504       OpalMixerNode * node ///< node associated with name
505     );
506 
507     /**Remove node's name from association list.
508       */
509     void RemoveNodeName(
510       PString name        ///< alias name for node
511     );
512 
513     /**Remove list of node names from association list.
514        Commonly used when node destroyed.
515       */
516     void RemoveNodeNames(
517       PStringList names   ///< list of alias names for nodes
518     );
519 
520     /**Queue user input for braodcast
521       */
522     void QueueUserInput(
523       const PSafePtr<OpalMixerNode> & node,     ///< Node to qhich user input is broadcast
524       const OpalMixerConnection * connection,   ///<  Connection NOT to send to
525       const PString & value                     ///<  String value of indication
526     );
527   //@}
528 
529   protected:
530     PSafeDictionary<PGloballyUniqueID, OpalMixerNode> m_nodesByUID;
531     PDictionary<PString, OpalMixerNode>               m_nodesByName;
532 
533     struct UserInput {
UserInputUserInput534       UserInput(
535         const PSafePtr<OpalMixerNode> & node,
536         const OpalMixerConnection * connection,
537         const PString & value
538       ) : m_node(node)
539         , m_connection(connection)
540         , m_value(value)
541       { }
542 
543       PSafePtr<OpalMixerNode> m_node;
544       const OpalMixerConnection * m_connection;
545       PString m_value;
546 
547       void Work();
548     };
549     PQueuedThreadPool<UserInput> m_userInputPool;
550 };
551 
552 
553 ///////////////////////////////////////////////////////////////////////////////
554 
555 /** Mixer EndPoint.
556     This class represents an endpoint that mixes media. It can be used as the
557     basis for a Multipoint Conferencing Unit.
558  */
559 class OpalMixerEndPoint : public OpalLocalEndPoint
560 {
561     PCLASSINFO(OpalMixerEndPoint, OpalLocalEndPoint);
562   public:
563   /**@name Construction */
564   //@{
565     /**Create a new endpoint.
566      */
567     OpalMixerEndPoint(
568       OpalManager & manager,  ///<  Manager of all endpoints.
569       const char * prefix     ///<  Prefix for URL style address strings
570     );
571 
572     /**Destroy endpoint.
573      */
574     ~OpalMixerEndPoint();
575 
576     /**Shut down the endpoint, this is called by the OpalManager just before
577        destroying the object and can be handy to make sure some things are
578        stopped before the vtable gets clobbered.
579       */
580     virtual void ShutDown();
581   //@}
582 
583   /**@name Overrides from OpalEndPoint */
584   //@{
585     /**Get the data formats this endpoint is capable of operating.
586        This provides a list of media data format names that may be used by an
587        OpalMediaStream may be created by a connection from this endpoint.
588 
589        Note that a specific connection may not actually support all of the
590        media formats returned here, but should return no more.
591 
592        The default behaviour returns the most basic media formats, PCM audio
593        and YUV420P video.
594       */
595     virtual OpalMediaFormatList GetMediaFormats() const;
596 
597     /**Set up a connection to a remote party.
598        This is called from the OpalManager::MakeConnection() function once
599        it has determined that this is the endpoint for the protocol.
600 
601        The general form for this party parameter is:
602 
603             [proto:][alias@][transport$]address[:port]
604 
605        where the various fields will have meanings specific to the endpoint
606        type. For example, with H.323 it could be "h323:Fred@site.com" which
607        indicates a user Fred at gatekeeper size.com. Whereas for the PSTN
608        endpoint it could be "pstn:5551234" which is to call 5551234 on the
609        first available PSTN line.
610 
611        The proto field is optional when passed to a specific endpoint. If it
612        is present, however, it must agree with the endpoints protocol name or
613        false is returned.
614 
615        This function usually returns almost immediately with the connection
616        continuing to occur in a new background thread.
617 
618        If false is returned then the connection could not be established. For
619        example if a PSTN endpoint is used and the assiciated line is engaged
620        then it may return immediately. Returning a non-NULL value does not
621        mean that the connection will succeed, only that an attempt is being
622        made.
623 
624        The default behaviour is pure.
625      */
626     virtual PSafePtr<OpalConnection> MakeConnection(
627       OpalCall & call,           ///<  Owner of connection
628       const PString & party,     ///<  Remote party to call
629       void * userData = NULL,    ///<  Arbitrary data to pass to connection
630       unsigned options = 0,      ///< Option bit mask to pass to connection
631       OpalConnection::StringOptions * stringOptions = NULL ///< Options to pass to connection
632     );
633 
634     /** Execute garbage collection for endpoint.
635         Returns true if all garbage has been collected.
636         Default behaviour deletes the objects in the connectionsActive list.
637       */
638     virtual PBoolean GarbageCollection();
639   //@}
640 
641   /**@name Operations */
642   //@{
643     /**Find a connection that uses the specified token.
644        This searches the endpoint for the connection that contains the token
645        as provided by functions such as MakeConnection(). If not then it
646        attempts to use the token as a OpalCall token and find a connection
647        of the same class.
648       */
649     PSafePtr<OpalMixerConnection> GetMixerConnectionWithLock(
650       const PString & token,     ///<  Token to identify connection
651       PSafetyMode mode = PSafeReadWrite ///< Lock mode
652     ) { return GetConnectionWithLockAs<OpalMixerConnection>(token, mode); }
653 
654     /**Create a connection for the PCSS endpoint.
655        The default implementation is to create a OpalMixerConnection.
656       */
657     virtual OpalMixerConnection * CreateConnection(
658       PSafePtr<OpalMixerNode> node, ///<  Node the connection is in
659       OpalCall & call,              ///<  Owner of connection
660       void * userData,              ///<  Arbitrary data to pass to connection
661       unsigned options,             ///< Option bit mask to pass to connection
662       OpalConnection::StringOptions * stringOptions ///< Options to pass to connection
663     );
664   //@}
665 
666   /**@name Mixer Operations */
667   //@{
668     /**Add a new node.
669        The info variable should be created on the heap and it is subsequently
670        owned by the node. NULL can be passed if defaults are to be used.
671 	   Calls CreateNode.
672       */
673     PSafePtr<OpalMixerNode> AddNode(
674       OpalMixerNodeInfo * info ///< Initial info for node
675     );
676 
677     /**Create a new node.
678        This should create the new instance of the OpalMixerNode as required
679        by the derived class, if any.
680        The info variable should be created on the heap and it is subsequently
681        owned by the node. NULL can be passed if defaults are to be used.
682       */
683     virtual OpalMixerNode * CreateNode(
684       OpalMixerNodeInfo * info ///< Initial info for node
685     );
686 
687     /**Get the first node.
688        The active nodes may be enumerated by the ++ operator on the PSafePtr.
689       */
690     PSafePtr<OpalMixerNode> GetFirstNode(
691       PSafetyMode mode = PSafeReference ///< Lock mode for returned pointer
692     ) const { return m_nodeManager.GetFirstNode(mode); }
693 
694     /**Find an existing node.
695        This will search for the mixer node using GUID and then name.
696       */
697     PSafePtr<OpalMixerNode> FindNode(
698       const PString & name,             ///< GUID or alias name for node
699       PSafetyMode mode = PSafeReference ///< Lock mode for returned pointer
700     ) { return m_nodeManager.FindNode(name, mode); }
701 
702     /**Remove a node.
703        Shut down all active connections with node, remove its name
704 	   associations and delete it.
705       */
RemoveNode(OpalMixerNode & node)706     void RemoveNode(
707       OpalMixerNode & node ///< Initial info for node
708     ) { m_nodeManager.RemoveNode(node); }
709   //@}
710 
711   /**@name Member variable access */
712   //@{
713     /**Set default ad hoc node information.
714        The pointer is passed to the CreateNode() function, so may be a
715        reference to derived class, which a derived class of OpalMixerNode
716        could use.
717 
718        Note if NULL, then ad hoc nodes are not created and incoming
719        connections are refused. A user must ex[icitly call AddNode() to create
720        a name that can be conected to.
721 
722        The version that takes a reference will utilise the CLone() function
723        to create a copy of the mixer info.
724       */
725     void SetAdHocNodeInfo(
726       const OpalMixerNodeInfo & info
727     );
728     void SetAdHocNodeInfo(
729       OpalMixerNodeInfo * info
730     );
731 
732     /**Get default ad hoc mode information.
733        The pointer returned from this function is passed to the CreateNode()
734        function, so may be a reference to derived class, which a derived class
735        of OpalMixerNode could use.
736 
737        Note if NULL, then ad hoc nodes are not created and incoming
738        connections are refused. A user must ex[icitly call AddNode() to create
739        a name that can be conected to.
740 
741        Default bahaviour returns member variable m_adHocNodeInfo.
742       */
GetAdHocNodeInfo()743     OpalMixerNodeInfo * GetAdHocNodeInfo() { return m_adHocNodeInfo; }
744 
745     /**Get the Node Manager for this endpoint.
746       */
GetNodeManager()747     const OpalMixerNodeManager & GetNodeManager() const { return m_nodeManager; }
GetNodeManager()748           OpalMixerNodeManager & GetNodeManager()       { return m_nodeManager; }
749   //@}
750 
751   protected:
752     OpalMixerNodeInfo  * m_adHocNodeInfo;
753     OpalMixerNodeManager m_nodeManager;
754 };
755 
756 
757 ///////////////////////////////////////////////////////////////////////////////
758 
759 /** Mixer connection.
760  */
761 class OpalMixerConnection : public OpalLocalConnection
762 {
763     PCLASSINFO(OpalMixerConnection, OpalLocalConnection);
764   public:
765   /**@name Construction */
766   //@{
767     /**Create a new connection.
768      */
769     OpalMixerConnection(
770       PSafePtr<OpalMixerNode> node, ///<  Node the connection is in
771       OpalCall & call,              ///<  Owner calll for connection
772       OpalMixerEndPoint & endpoint, ///<  Owner endpoint for connection
773       void * userData,              ///<  Arbitrary data to pass to connection
774       unsigned options = 0,         ///< Option bit map to be passed to connection
775       OpalConnection::StringOptions * stringOptions = NULL ///< Options to be passed to connection
776     );
777 
778     /**Destroy connection.
779      */
780     ~OpalMixerConnection();
781   //@}
782 
783   /**@name Overrides from OpalConnection */
784   //@{
785     /**Clean up the termination of the connection.
786        This function can do any internal cleaning up and waiting on background
787        threads that may be using the connection object.
788 
789        Note that there is not a one to one relationship with the
790        OnEstablishedConnection() function. This function may be called without
791        that function being called. For example if SetUpConnection() was used
792        but the call never completed.
793 
794        Classes that override this function should make sure they call the
795        ancestor version for correct operation.
796 
797        An application will not typically call this function as it is used by
798        the OpalManager during a release of the connection.
799 
800        The default behaviour calls the OpalEndPoint function of the same name.
801       */
802     virtual void OnReleased();
803 
804     /**Get the data formats this connection is capable of operating.
805        This provides a list of media data format names that a
806        OpalMediaStream may be created in within this connection.
807 
808        The default behaviour calls GetMediaFormats() on the endpoint.
809       */
810     virtual OpalMediaFormatList GetMediaFormats() const;
811 
812     /**Open a new media stream.
813        This will create a media stream of an appropriate subclass as required
814        by the underlying connection protocol. For instance H.323 would create
815        an OpalRTPStream.
816 
817        The sessionID parameter may not be needed by a particular media stream
818        and may be ignored. In the case of an OpalRTPStream it us used.
819 
820        Note that media streams may be created internally to the underlying
821        protocol. This function is not the only way a stream can come into
822        existance.
823 
824        The default behaviour is pure.
825      */
826     virtual OpalMediaStream * CreateMediaStream(
827       const OpalMediaFormat & mediaFormat, ///<  Media format for stream
828       unsigned sessionID,                  ///<  Session number for stream
829       PBoolean isSource                    ///<  Is a source stream
830     );
831 
832     /**Call back when media stream patch thread starts.
833       */
834     virtual void OnStartMediaPatch(
835       OpalMediaPatch & patch    ///< Patch being started
836     );
837 
838     /// Call back for connection to act on changed string options
839     virtual void OnApplyStringOptions();
840 
841     /**Send a user input indication to the remote endpoint.
842        This is for sending arbitrary strings as user indications.
843 
844        The default behaviour is to call SendUserInputTone() for each character
845        in the string.
846       */
847     virtual PBoolean SendUserInputString(
848       const PString & value                   ///<  String value of indication
849     );
850 
851     /**Send a user input indication to the remote endpoint.
852        This sends DTMF emulation user input. If something more sophisticated
853        than the simple tones that can be sent using the SendUserInput()
854        function.
855 
856        A duration of zero indicates that no duration is to be indicated.
857        A non-zero logical channel indicates that the tone is to be syncronised
858        with the logical channel at the rtpTimestamp value specified.
859 
860        The tone parameter must be one of "0123456789#*ABCD!" where '!'
861        indicates a hook flash. If tone is a ' ' character then a
862        signalUpdate PDU is sent that updates the last tone indication
863        sent. See the H.245 specifcation for more details on this.
864 
865        The default behaviour sends the tone using RFC2833.
866       */
867     virtual PBoolean SendUserInputTone(
868       char tone,        ///<  DTMF tone code
869       unsigned duration = 0  ///<  Duration of tone in milliseconds
870     );
871   //@}
872 
873   /**@name Operations */
874   //@{
875     /**Set this connection to listen only mode.
876       */
877     void SetListenOnly(
878       bool listenOnly   ///< New listen only state.
879     );
880 
881     /**Get flag for this connection is in listen only mode.
882       */
GetListenOnly()883     bool GetListenOnly() const { return m_listenOnly; }
884 
885     /**Get the node that this connection is being mxied in.
886       */
GetNode()887     PSafePtr<OpalMixerNode> GetNode() const { return m_node; }
888   //@}
889 
890   protected:
891     OpalMixerEndPoint     & m_endpoint;
892     PSafePtr<OpalMixerNode> m_node;
893     bool                    m_listenOnly;
894 };
895 
896 
897 /**Mixer media stream.
898    This class represents a media stream that will send/get media from a mixer.
899  */
900 class OpalMixerMediaStream : public OpalMediaStream
901 {
902     PCLASSINFO(OpalMixerMediaStream, OpalMediaStream);
903   public:
904   /**@name Construction */
905   //@{
906     /**Construct a new media stream for mixer.
907       */
908     OpalMixerMediaStream(
909       OpalConnection & conn,               ///<  Connection for media stream
910       const OpalMediaFormat & mediaFormat, ///<  Media format for stream
911       unsigned sessionID,                  ///<  Session number for stream
912       bool isSource,                       ///<  Is a source stream
913       PSafePtr<OpalMixerNode> node,        ///<  Mixer node to send data
914       bool listenOnly                      ///<  Effectively initial pause state
915     );
916 
917     /**Destroy stream.
918       */
919     ~OpalMixerMediaStream();
920   //@}
921 
922   /**@name Overrides of OpalMediaStream class */
923   //@{
924     /**Open the media stream using the media format.
925       */
926     virtual PBoolean Open();
927 
928     /**Write an RTP frame of data to the sink media stream.
929        The default behaviour simply calls WriteData() on the data portion of the
930        RTP_DataFrame and and sets the internal timestamp and marker from the
931        member variables of the media stream class.
932       */
933     virtual PBoolean WritePacket(
934       RTP_DataFrame & packet
935     );
936 
937     /**Indicate if the media stream is synchronous.
938        Returns true for LID streams.
939       */
940     virtual PBoolean IsSynchronous() const;
941 
942     /**Indicate if the media stream requires a OpalMediaPatch thread (active patch).
943        This is called on the source/sink stream and is passed the sink/source
944        stream that the patch will initially be using. The function could
945        conditionally require the patch thread to execute a thread reading and
946        writing data, or prevent  it from doing so as it can do so in hardware
947        in some way.
948 
949        The default behaviour returns true if a sink stream. If source stream
950        then threading is from the mixer class.
951       */
952     virtual PBoolean RequiresPatchThread() const;
953 
954     /**Enable jitter buffer for the media stream.
955        Returns true if a jitter buffer is enabled/disabled. Returns false if
956        no jitter buffer exists for the media stream.
957 
958        The default behaviour sets the mixer jitter buffer size according
959        to the connection parameters, then returns true.
960       */
961     virtual bool EnableJitterBuffer(bool enab = true) const;
962   //@}
963 
964   /**@name Member variable access */
965   //@{
966     /**Get the mixer node for this stream.
967      */
GetNode()968     PSafePtr<OpalMixerNode> GetNode() { return m_node; }
969   //@}
970 
971   protected:
972     virtual void InternalClose();
973 
974     PSafePtr<OpalMixerNode> m_node;
975     bool m_listenOnly;
976 #if OPAL_VIDEO
977     bool m_video;
978 #endif
979 };
980 
981 
982 /** Mixer node.
983     This class represents a group of connections that are being mixed.
984   */
985 class OpalMixerNode : public PSafeObject
986 {
987     PCLASSINFO(OpalMixerNode, PSafeObject);
988   public:
989   /**@name Construction */
990   //@{
991     /**Create a new node.
992      */
993     OpalMixerNode(
994       OpalMixerNodeManager & manager, ///< Manager for this node
995       OpalMixerNodeInfo * info        ///< Configuration information
996     );
997     OpalMixerNode(
998       OpalMixerEndPoint & endpoint,   ///< Endpoint for this node
999       OpalMixerNodeInfo * info        ///< Configuration information
1000     );
1001 
1002     /**Destroy node.
1003      */
1004     ~OpalMixerNode();
1005 
1006     /**Shut down node.
1007        This clears all attached connections, removes all names and generally
1008        shuts the node down.
1009       */
1010     void ShutDown();
1011   //@}
1012 
1013   /**@name Overrides from PObject */
1014   //@{
1015     /**Standard stream print function.
1016        The PObject class has a << operator defined that invokes this function
1017        polymorphically.
1018       */
1019     void PrintOn(
1020       ostream & strm    ///<  Stream to output text representation
1021     ) const;
1022   //@}
1023 
1024   /**@name Operations */
1025   //@{
1026     /**Attach a connection.
1027       */
1028     void AttachConnection(
1029       OpalConnection * connection  ///< Connection to attach
1030     );
1031 
1032     /**Detach a connection.
1033       */
1034     void DetachConnection(
1035       OpalConnection * connection  ///< Connection to detach
1036     );
1037 
1038     /**Attach a stream for output.
1039       */
1040     bool AttachStream(
1041       OpalMixerMediaStream * stream     ///< Stream to attach
1042     );
1043 
1044     /**Detach a stream for output.
1045       */
1046     void DetachStream(
1047       OpalMixerMediaStream * stream     ///< Stream to detach
1048     );
1049 
1050     /**Use media bypass if applicable.
1051       */
1052     void UseMediaPassThrough(
1053       unsigned sessionID,                 ///< Session ID to bypass, 0 indicates all
1054       OpalConnection * connection = NULL  ///< Just deleted connection
1055     );
1056 
1057     /**Sets the size of the jitter buffer to be used by the specified stream
1058        in this mixer. A mixer defaults to not having any jitter buffer enabled.
1059 
1060        If either jitter delay parameter is zero, it destroys the jitter buffer
1061        attached to this mixer.
1062       */
SetJitterBufferSize(const OpalBaseMixer::Key_T & key,unsigned minJitterDelay,unsigned maxJitterDelay)1063     bool SetJitterBufferSize(
1064       const OpalBaseMixer::Key_T & key, ///< key for mixer stream
1065       unsigned minJitterDelay,          ///<  Minimum jitter buffer delay in RTP timestamp units
1066       unsigned maxJitterDelay           ///<  Maximum jitter buffer delay in RTP timestamp units
1067     ) { return m_audioMixer.SetJitterBufferSize(key, minJitterDelay, maxJitterDelay); }
1068 
1069     /**Write data to mixer.
1070       */
WriteAudio(const OpalBaseMixer::Key_T & key,const RTP_DataFrame & input)1071     bool WriteAudio(
1072       const OpalBaseMixer::Key_T & key, ///< key for mixer stream
1073       const RTP_DataFrame & input       ///< Input RTP data for media
1074     ) { return m_audioMixer.WriteStream(key, input); }
1075 
1076 #if OPAL_VIDEO
1077     /**Write data to mixer.
1078       */
WriteVideo(const OpalBaseMixer::Key_T & key,const RTP_DataFrame & input)1079     bool WriteVideo(
1080       const OpalBaseMixer::Key_T & key, ///< key for mixer stream
1081       const RTP_DataFrame & input       ///< Input RTP data for media
1082     ) { return m_videoMixer.WriteStream(key, input); }
1083 #endif // OPAL_VIDEO
1084 
1085     /**Send a user input indication to all connections.
1086       */
1087     virtual void BroadcastUserInput(
1088       const OpalConnection * connection,      ///<  Connection NOT to send to
1089       const PString & value                   ///<  String value of indication
1090     );
1091   //@}
1092 
1093   /**@name Member variable access */
1094   //@{
1095     /**Get globally unique identifier for node.
1096       */
GetGUID()1097     const PGloballyUniqueID & GetGUID() const { return m_guid; }
1098 
1099     /**Get list of names for this node.
1100       */
GetNames()1101     const PStringList & GetNames() const { return m_names; }
1102 
1103     /**Add a name for this node.
1104       */
1105     void AddName(
1106       const PString & name
1107     );
1108 
1109     /**Remove a name for this node.
1110       */
1111     void RemoveName(
1112       const PString & name
1113     );
1114 
1115     /**Get count of connections.
1116        Note that as this value can change ata any moent, it is really not
1117        that useful and should definitely not be used for enumeration of the
1118        connections.
1119       */
GetConnectionCount()1120     PINDEX GetConnectionCount() const { return m_connections.GetSize(); }
1121 
1122     /**Get first connection in the connections list as type.
1123       */
1124     template <class Subclass>
1125     PSafePtr<Subclass> GetFirstConnectionAs(
1126       PSafetyMode mode = PSafeReference
1127     ) const { return PSafePtr<Subclass>(m_connections, mode); }
1128 
1129     /**Get first connection in the connections list.
1130       */
1131     PSafePtr<OpalConnection> GetFirstConnection(
1132       PSafetyMode mode = PSafeReference
1133     ) const { return GetFirstConnectionAs<OpalConnection>(mode); }
1134 
1135     /**Get the raw audio accumulation buffer.
1136      */
GetNodeInfo()1137     const OpalMixerNodeInfo & GetNodeInfo() { return *m_info; }
1138 
1139     /**Get the creation time of the node.
1140      */
GetCreationTime()1141     const PTime & GetCreationTime() const { return m_creationTime; }
1142   //@}
1143 
1144   protected:
1145     void Construct();
1146 
1147     OpalMixerNodeManager & m_manager;
1148     PGloballyUniqueID      m_guid;
1149     PStringList            m_names;
1150     OpalMixerNodeInfo    * m_info;
1151     PTime                  m_creationTime;
1152 
1153     PSafeList<OpalConnection> m_connections;
1154 
1155     struct MediaMixer
1156     {
1157       MediaMixer();
1158 
1159       PSafeList<OpalMixerMediaStream> m_outputStreams;
1160     };
1161 
1162     struct AudioMixer : public OpalAudioMixer, public MediaMixer
1163     {
1164       AudioMixer(const OpalMixerNodeInfo & info);
1165       ~AudioMixer();
1166 
1167       virtual bool OnPush();
1168 
1169       struct CachedAudio {
1170         CachedAudio();
1171         ~CachedAudio();
1172         enum { Collecting, Collected, Completed } m_state;
1173         RTP_DataFrame    m_raw;
1174         RTP_DataFrame    m_encoded;
1175         OpalTranscoder * m_transcoder;
1176       };
1177       std::map<PString, CachedAudio> m_cache;
1178 
1179       void PushOne(
1180         PSafePtr<OpalMixerMediaStream> & stream,
1181         CachedAudio & cache,
1182         const short * audioToSubtract
1183       );
1184 #ifdef OPAL_MIXER_AUDIO_DEBUG
1185       class PAudioMixerDebug * m_audioDebug;
1186 #endif
1187     };
1188     AudioMixer m_audioMixer;
1189 
1190 #if OPAL_VIDEO
1191     struct VideoMixer : public OpalVideoMixer, public MediaMixer
1192     {
1193       VideoMixer(const OpalMixerNodeInfo & info);
1194       ~VideoMixer();
1195 
1196       virtual bool OnMixed(RTP_DataFrame * & output);
1197 
1198       PDictionary<PString, OpalTranscoder> m_transcoders;
1199     };
1200     VideoMixer m_videoMixer;
1201 #endif // OPAL_VIDEO
1202 };
1203 
1204 
1205 #endif // OPAL_OPAL_OPAL_MIXER
1206 
1207 
1208 ///////////////////////////////////////////////////////////////////////////////
1209