1 /*
2  * mediafmt.h
3  *
4  * Media Format descriptions
5  *
6  * Open Phone Abstraction Library (OPAL)
7  * Formally known as the Open H323 project.
8  *
9  * Copyright (c) 2001 Equivalence Pty. Ltd.
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 H323 Library.
22  *
23  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24  *
25  * Contributor(s): ______________________________________.
26  *
27  * $Revision: 27856 $
28  * $Author: rjongbloed $
29  * $Date: 2012-06-18 21:51:57 -0500 (Mon, 18 Jun 2012) $
30  */
31 
32 #ifndef OPAL_OPAL_MEDIAFMT_H
33 #define OPAL_OPAL_MEDIAFMT_H
34 
35 #ifdef P_USE_PRAGMA
36 #pragma interface
37 #endif
38 
39 #ifdef _MSC_VER
40 #if _MSC_VER < 1300
41 #pragma warning(disable:4663)
42 #endif
43 #endif
44 
45 #include <opal/buildopts.h>
46 
47 #include <opal/mediatype.h>
48 #include <rtp/rtp.h>
49 
50 #if OPAL_VIDEO
51 #include <ptlib/videoio.h>
52 #endif
53 
54 #include <limits>
55 
56 #ifdef min
57 #undef min
58 #endif
59 #ifdef max
60 #undef max
61 #endif
62 
63 class OpalMediaFormat;
64 
65 
66 ///////////////////////////////////////////////////////////////////////////////
67 
68 PLIST(OpalMediaFormatBaseList, OpalMediaFormat);
69 
70 /**This class contains a list of media formats.
71   */
72 class OpalMediaFormatList : public OpalMediaFormatBaseList
73 {
74   PCLASSINFO(OpalMediaFormatList, OpalMediaFormatBaseList);
75   public:
76   /**@name Construction */
77   //@{
78     /**Create an empty media format list.
79      */
80     OpalMediaFormatList();
81 
82     /**Create a media format list with one media format in it.
83      */
84     OpalMediaFormatList(
85       const OpalMediaFormat & format    ///<  Format to add
86     );
87 
88     /**Create a copy of a media format list.
89      */
OpalMediaFormatList(const OpalMediaFormatList & l)90     OpalMediaFormatList(const OpalMediaFormatList & l) : OpalMediaFormatBaseList(l) { }
91   //@}
92 
93   /**@name Operations */
94   //@{
95     /**Add a format(s) to the list.
96        If any format is invalid or already in the list then it is not added.
97       */
98     OpalMediaFormatList & operator+=(
99       const char * wildcard    ///< Wildcard for formats to add
100     ) { PConstString s(wildcard); return operator+=(s); }
101 
102     /**Add a format(s) to the list.
103        If any format is invalid or already in the list then it is not added.
104       */
105     OpalMediaFormatList & operator+=(
106       const PString & wildcard    ///< Wildcard for formats to add
107     );
108 
109     /**Add a format to the list.
110        If the format is invalid or already in the list then it is not added.
111       */
112     OpalMediaFormatList & operator+=(
113       const OpalMediaFormat & format    ///<  Format to add
114     );
115 
116     /**Add a format to the list.
117        If the format is invalid or already in the list then it is not added.
118       */
119     OpalMediaFormatList & operator+=(
120       const OpalMediaFormatList & formats    ///<  Formats to add
121     );
122 
123     /**Remove a format to the list.
124        If the format is invalid or not in the list then this does nothing.
125       */
126     OpalMediaFormatList & operator-=(
127       const OpalMediaFormat & format    ///<  Format to remove
128     );
129 
130     /**Remove a format to the list.
131        If the format is invalid or not in the list then this does nothing.
132       */
133     OpalMediaFormatList & operator-=(
134       const OpalMediaFormatList & formats    ///<  Formats to remove
135     );
136 
137     /**Get a format iterator in the list matching the payload type.
138 
139 
140        Returns end() if not in list.
141       */
142     const_iterator FindFormat(
143       RTP_DataFrame::PayloadTypes rtpPayloadType, ///<  RTP payload type code
144       const unsigned clockRate,                   ///<  clock rate
145       const char * rtpEncodingName = NULL,        ///<  RTP payload type name
146       const char * protocol = NULL,               ///<  protocol to be valid for (if NULL, then all)
147       const_iterator start = const_iterator()     ///<  location to start search
148     ) const;
149 
150     /**Get a position in the list of the first entry matching the wildcard.
151        The wildcard string is a string match using several special
152        characters.
153 
154        The '*' character indicates substrings, for example: "G.711*" would
155        match "G.711-uLaw-64k" and "G.711-ALaw-64k".
156 
157        The '@' character indicates a type of media format, so say "\@video"
158        would find the first video codec.
159 
160        The '!' character indicates a negative test. That is the first entry
161        that does NOT match the string is returned. The string after the '!'
162        may contain '*' and '@' characters.
163 
164        Returns P_MAX_INDEX if not in list.
165       */
166     const_iterator FindFormat(
167       const PString & wildcard,    ///<  Wildcard string name.
168       const_iterator start = const_iterator() ///< Starting position iterator for search
169     ) const;
170 
171     /**Determine if a format matching the payload type is in the list.
172       */
HasFormat(RTP_DataFrame::PayloadTypes rtpPayloadType)173     PBoolean HasFormat(
174       RTP_DataFrame::PayloadTypes rtpPayloadType ///<  RTP payload type code
175     ) const { return FindFormat(rtpPayloadType) != end(); }
176 
177     /**Determine if a format matching the wildcard is in the list.
178        The wildcard string is a simple substring match using the '*'
179        character. For example: "G.711*" would match "G.711-uLaw-64k" and
180        "G.711-ALaw-64k".
181       */
HasFormat(const PString & wildcard)182     PBoolean HasFormat(
183       const PString & wildcard    ///<  Wildcard string name.
184     ) const { return FindFormat(wildcard) != end(); }
185 
186     /**Remove all the formats specified.
187        Each string in the array is checked using the wildcard matching algorithm in
188        FindFormat().
189 
190        The '*' character indicates substrings, for example: "G.711*" would
191        remove "G.711-uLaw-64k" and "G.711-ALaw-64k".
192 
193        The '@' character indicates a type of media format, so say "\@video"
194        would remove all video codecs.
195 
196        The '!' character indicates a negative test. That is the entres that do
197        NOT match the string are removed. The string after the '!' may contain
198        '*' and '@' characters.
199 
200        I should be noted that when the ! operator is used, they are combined
201        differently to the usual application of each entry in turn. Thus, the
202        array {"!A","!B"} will result in keeping <i>both</i> A and B formats.
203      */
204     void Remove(
205       const PStringArray & mask
206     );
207 
208     /**Reorder the formats in the list.
209        The order variable is an array of names and the list is reordered
210        according to the order in that array.
211 
212        Each string in the array is checked using the wildcard matching algorithm
213        similar to FindFormat().
214 
215        The '*' character indicates substrings, for example: "G.711*" would
216        match "G.711-uLaw-64k" and "G.711-ALaw-64k".
217 
218        The '@' character indicates a type of media format, so say "\@video"
219        would sort by video codec.
220 
221         The '!' character is not supported.
222       */
223     void Reorder(
224       const PStringArray & order
225     );
226 
227     /**Determine if a list contains a specific media type
228       */
229     bool HasType(
230       const OpalMediaType & type,
231       bool mustBeTransportable = true
232     ) const;
233   //@}
234 
235   private:
Append(PObject *)236     virtual PINDEX Append(PObject *) { return P_MAX_INDEX; }
Insert(const PObject &,PObject *)237     virtual PINDEX Insert(const PObject &, PObject *) { return P_MAX_INDEX; }
InsertAt(PINDEX,PObject *)238     virtual PINDEX InsertAt(PINDEX, PObject *) { return P_MAX_INDEX; }
SetAt(PINDEX,PObject *)239     virtual PBoolean SetAt(PINDEX, PObject *) { return false; }
240 };
241 
242 
243 ///////////////////////////////////////////////////////////////////////////////
244 
245 /**Base class for options attached to an OpalMediaFormat.
246   */
247 class OpalMediaOption : public PObject
248 {
249     PCLASSINFO(OpalMediaOption, PObject);
250   public:
251     // Note the below enum must be identical to PluginCodec_OptionMerge in opalplugin.h
252     enum MergeType {
253       NoMerge,
254       MinMerge,
255       MaxMerge,
256       EqualMerge,
257       NotEqualMerge,
258       AlwaysMerge,
259       CustomMerge,
260       IntersectionMerge, // Set intersection, applies to numeric (bit wise AND) or string (common substrings)
261 
262       // Synonyms
263       AndMerge = MinMerge,  // Applies to Boolean option or Enum with two elements
264       OrMerge  = MaxMerge   // Applies to Boolean option or Enum with two elements
265     };
266 
267   protected:
268     OpalMediaOption(
269       const PString & name
270     );
271     OpalMediaOption(
272       const char * name,
273       bool readOnly,
274       MergeType merge
275     );
276 
277   public:
278     virtual Comparison Compare(const PObject & obj) const;
279 
280     virtual bool Merge(
281       const OpalMediaOption & option
282     );
283 
284     virtual bool ValidateMerge(
285       const OpalMediaOption & option
286     ) const;
287 
288     virtual Comparison CompareValue(
289       const OpalMediaOption & option
290     ) const = 0;
291     virtual void Assign(
292       const OpalMediaOption & option
293     ) = 0;
294 
295     PString AsString() const;
296     bool FromString(const PString & value);
297 
GetName()298     const PString & GetName() const { return m_name; }
299 
IsReadOnly()300     bool IsReadOnly() const { return m_readOnly; }
SetReadOnly(bool readOnly)301     void SetReadOnly(bool readOnly) { m_readOnly = readOnly; }
302 
GetMerge()303     MergeType GetMerge() const { return m_merge; }
SetMerge(MergeType merge)304     void SetMerge(MergeType merge) { m_merge = merge; }
305 
306 #if OPAL_SIP
GetFMTPName()307     const PString & GetFMTPName() const { return m_FMTPName; }
SetFMTPName(const char * name)308     void SetFMTPName(const char * name) { m_FMTPName = name; }
309 
GetFMTPDefault()310     const PString & GetFMTPDefault() const { return m_FMTPDefault; }
SetFMTPDefault(const char * value)311     void SetFMTPDefault(const char * value) { m_FMTPDefault = value; }
312 #endif // OPAL_SIP
313 
314 #if OPAL_H323
315     struct H245GenericInfo {
H245GenericInfoH245GenericInfo316       H245GenericInfo()
317         : ordinal(0)
318         , mode(None)
319         , integerType(UnsignedInt)
320         , excludeTCS(false)
321         , excludeOLC(false)
322         , excludeReqMode(false)
323         , position(-1)
324       { }
325 
326       unsigned ordinal;
327 
328       enum Modes {
329         None,
330         Collapsing,
331         NonCollapsing
332       } mode;
333 
334       enum IntegerTypes {
335         UnsignedInt,
336         Unsigned32,
337         BooleanArray
338       } integerType;
339 
340       bool    excludeTCS;
341       bool    excludeOLC;
342       bool    excludeReqMode;
343       int     position;     // Position in sequence for parameter
344       PString defaultValue; // Do not include parameter if this value
345     };
346 
GetH245Generic()347     const H245GenericInfo & GetH245Generic() const { return m_H245Generic; }
SetH245Generic(const H245GenericInfo & genericInfo)348     void SetH245Generic(const H245GenericInfo & genericInfo) { m_H245Generic = genericInfo; }
349 #endif // OPAL_H323
350 
351   protected:
352     PCaselessString m_name;
353     bool            m_readOnly;
354     MergeType       m_merge;
355 
356 #if OPAL_SIP
357     PCaselessString m_FMTPName;
358     PString         m_FMTPDefault;
359 #endif // OPAL_SIP
360 
361 #if OPAL_H323
362     H245GenericInfo m_H245Generic;
363 #endif // OPAL_H323
364 };
365 
366 
367 template <typename T>
368 class OpalMediaOptionValue : public OpalMediaOption
369 {
370     PCLASSINFO(OpalMediaOptionValue, OpalMediaOption);
371   public:
372     OpalMediaOptionValue(
373       const char * name,
374       bool readOnly,
375       OpalMediaOption::MergeType merge = OpalMediaOption::MinMerge,
376       T value = T()
377     )
OpalMediaOption(name,readOnly,merge)378       : OpalMediaOption(name, readOnly, merge)
379       , m_value(value)
380     {
381     }
382 
Clone()383     virtual PObject * Clone() const
384     {
385       return new OpalMediaOptionValue(*this);
386     }
387 
PrintOn(ostream & strm)388     virtual void PrintOn(ostream & strm) const
389     {
390       strm << m_value;
391     }
392 
ReadFrom(istream & strm)393     virtual void ReadFrom(istream & strm)
394     {
395       strm >> m_value;
396     }
397 
Merge(const OpalMediaOption & option)398     virtual bool Merge(const OpalMediaOption & option)
399     {
400       if (m_merge != IntersectionMerge)
401         return OpalMediaOption::Merge(option);
402 
403       const OpalMediaOptionValue * otherOption = PDownCast(const OpalMediaOptionValue, &option);
404       if (otherOption == NULL)
405         return false;
406 
407       m_value &= otherOption->m_value;
408       return true;
409     }
410 
CompareValue(const OpalMediaOption & option)411     virtual Comparison CompareValue(const OpalMediaOption & option) const
412     {
413       const OpalMediaOptionValue * otherOption = PDownCast(const OpalMediaOptionValue, &option);
414       if (otherOption == NULL)
415         return GreaterThan;
416       if (m_value < otherOption->m_value)
417         return LessThan;
418       if (m_value > otherOption->m_value)
419         return GreaterThan;
420       return EqualTo;
421     }
422 
Assign(const OpalMediaOption & option)423     virtual void Assign(const OpalMediaOption & option)
424     {
425       const OpalMediaOptionValue * otherOption = PDownCast(const OpalMediaOptionValue, &option);
426       if (otherOption != NULL)
427         m_value = otherOption->m_value;
428     }
429 
GetValue()430     T GetValue() const
431     {
432       return m_value;
433     }
434 
SetValue(T value)435     void SetValue(T value)
436     {
437       m_value = value;
438     }
439 
440   protected:
441     T m_value;
442 };
443 
444 
445 template <typename T>
446 class OpalMediaOptionNumericalValue : public OpalMediaOptionValue<T>
447 {
448     typedef OpalMediaOptionValue<T> BaseClass;
449     PCLASSINFO(OpalMediaOptionNumericalValue, BaseClass);
450   public:
451     OpalMediaOptionNumericalValue(
452       const char * name,
453       bool readOnly,
454       OpalMediaOption::MergeType merge = OpalMediaOption::MinMerge,
455       T value = 0,
456       T minimum = std::numeric_limits<T>::min(),
457       T maximum = std::numeric_limits<T>::max()
458     )
BaseClass(name,readOnly,merge,value)459       : BaseClass(name, readOnly, merge, value)
460       , m_minimum(minimum)
461       , m_maximum(maximum)
462     {
463     }
464 
Clone()465     virtual PObject * Clone() const
466     {
467       return new OpalMediaOptionNumericalValue(*this);
468     }
469 
ReadFrom(istream & strm)470     virtual void ReadFrom(istream & strm)
471     {
472       T temp = 0;
473       strm >> temp;
474       if (strm.fail())
475         return;
476       if (temp >= m_minimum && temp <= m_maximum)
477         this->m_value = temp;
478       else
479         strm.setstate(ios::badbit);
480     }
481 
SetValue(T value)482     void SetValue(T value)
483     {
484       if (value < m_minimum)
485         this->m_value = m_minimum;
486       else if (value > m_maximum)
487         this->m_value = m_maximum;
488       else
489         this->m_value = value;
490     }
491 
SetMinimum(T m)492     void SetMinimum(T m)
493     {
494       this->m_minimum = m;
495     }
496 
SetMaximum(T m)497     void SetMaximum(T m)
498     {
499       this->m_maximum = m;
500     }
501 
502   protected:
503     T m_minimum;
504     T m_maximum;
505 };
506 
507 
508 typedef OpalMediaOptionNumericalValue<bool>     OpalMediaOptionBoolean;
509 typedef OpalMediaOptionNumericalValue<int>      OpalMediaOptionInteger;
510 typedef OpalMediaOptionNumericalValue<unsigned> OpalMediaOptionUnsigned;
511 
512 // Wrapper class so we can implement intersection (&= operator) for floating point
513 class OpalMediaOptionRealValue
514 {
515     double m_value;
516   public:
m_value(value)517     OpalMediaOptionRealValue(double value = 0) : m_value(value) { }
518     operator double() const { return m_value; }
519     void operator&=(double other) { if (m_value > other) m_value = other; }
520     friend ostream & operator<<(ostream & strm, const OpalMediaOptionRealValue & value) { return strm << value.m_value; }
521     friend istream & operator>>(istream & strm,       OpalMediaOptionRealValue & value) { return strm >> value.m_value; }
522 };
523 
524 typedef OpalMediaOptionNumericalValue<OpalMediaOptionRealValue> OpalMediaOptionReal;
525 
526 
527 class OpalMediaOptionEnum : public OpalMediaOption
528 {
529     PCLASSINFO(OpalMediaOptionEnum, OpalMediaOption);
530   public:
531     OpalMediaOptionEnum(
532       const char * name,
533       bool readOnly
534     );
535     OpalMediaOptionEnum(
536       const char * name,
537       bool readOnly,
538       const char * const * enumerations,
539       PINDEX count,
540       MergeType merge = EqualMerge,
541       PINDEX value = 0
542     );
543 
544     virtual PObject * Clone() const;
545     virtual void PrintOn(ostream & strm) const;
546     virtual void ReadFrom(istream & strm);
547 
548     virtual Comparison CompareValue(const OpalMediaOption & option) const;
549     virtual void Assign(const OpalMediaOption & option);
550 
GetValue()551     PINDEX GetValue() const { return m_value; }
552     void SetValue(PINDEX value);
553 
GetEnumerations()554     const PStringArray & GetEnumerations() const { return m_enumerations; }
SetEnumerations(const PStringArray & e)555     void SetEnumerations(const PStringArray & e)
556     {
557       m_enumerations = e;
558     }
559 
560   protected:
561     PStringArray m_enumerations;
562     PINDEX       m_value;
563 };
564 
565 
566 class OpalMediaOptionString : public OpalMediaOption
567 {
568     PCLASSINFO(OpalMediaOptionString, OpalMediaOption);
569   public:
570     OpalMediaOptionString(
571       const char * name,
572       bool readOnly
573     );
574     OpalMediaOptionString(
575       const char * name,
576       bool readOnly,
577       const PString & value
578     );
579 
580     virtual PObject * Clone() const;
581     virtual void PrintOn(ostream & strm) const;
582     virtual void ReadFrom(istream & strm);
583 
584     virtual bool Merge(const OpalMediaOption & option);
585     virtual Comparison CompareValue(const OpalMediaOption & option) const;
586     virtual void Assign(const OpalMediaOption & option);
587 
GetValue()588     const PString & GetValue() const { return m_value; }
589     void SetValue(const PString & value);
590 
591   protected:
592     PString m_value;
593 };
594 
595 
596 class OpalMediaOptionOctets : public OpalMediaOption
597 {
598     PCLASSINFO(OpalMediaOptionOctets, OpalMediaOption);
599   public:
600     OpalMediaOptionOctets(
601       const char * name,
602       bool readOnly,
603       bool base64 = false
604     );
605     OpalMediaOptionOctets(
606       const char * name,
607       bool readOnly,
608       bool base64,
609       const PBYTEArray & value
610     );
611     OpalMediaOptionOctets(
612       const char * name,
613       bool readOnly,
614       bool base64,
615       const BYTE * data,
616       PINDEX length
617     );
618 
619     virtual PObject * Clone() const;
620     virtual void PrintOn(ostream & strm) const;
621     virtual void ReadFrom(istream & strm);
622 
623     virtual Comparison CompareValue(const OpalMediaOption & option) const;
624     virtual void Assign(const OpalMediaOption & option);
625 
GetValue()626     const PBYTEArray & GetValue() const { return m_value; }
627     void SetValue(const PBYTEArray & value);
628     void SetValue(const BYTE * data, PINDEX length);
629 
SetBase64(bool b)630     void SetBase64(bool b)
631     {
632       m_base64 = b;
633     }
634 
635   protected:
636     PBYTEArray m_value;
637     bool       m_base64;
638 };
639 
640 
641 ///////////////////////////////////////////////////////////////////////////////
642 
643 class OpalMediaFormatInternal : public PObject
644 {
645     PCLASSINFO(OpalMediaFormatInternal, PObject);
646   public:
647     OpalMediaFormatInternal(
648       const char * fullName,
649       const OpalMediaType & mediaType,
650       RTP_DataFrame::PayloadTypes rtpPayloadType,
651       const char * encodingName,
652       PBoolean     needsJitter,
653       unsigned bandwidth,
654       PINDEX   frameSize,
655       unsigned frameTime,
656       unsigned clockRate,
657       time_t timeStamp
658     );
659 
GetName()660     const PCaselessString & GetName() const { return formatName; }
661 
662     virtual PObject * Clone() const;
663     virtual void PrintOn(ostream & strm) const;
664 
665     virtual bool IsValid() const;
666     virtual bool IsTransportable() const;
667 
668     virtual PStringToString GetOptions() const;
669     virtual bool GetOptionValue(const PString & name, PString & value) const;
670     virtual bool SetOptionValue(const PString & name, const PString & value);
671     virtual bool GetOptionBoolean(const PString & name, bool dflt) const;
672     virtual bool SetOptionBoolean(const PString & name, bool value);
673     virtual int GetOptionInteger(const PString & name, int dflt) const;
674     virtual bool SetOptionInteger(const PString & name, int value);
675     virtual double GetOptionReal(const PString & name, double dflt) const;
676     virtual bool SetOptionReal(const PString & name, double value);
677     virtual PINDEX GetOptionEnum(const PString & name, PINDEX dflt) const;
678     virtual bool SetOptionEnum(const PString & name, PINDEX value);
679     virtual PString GetOptionString(const PString & name, const PString & dflt) const;
680     virtual bool SetOptionString(const PString & name, const PString & value);
681     virtual bool GetOptionOctets(const PString & name, PBYTEArray & octets) const;
682     virtual bool SetOptionOctets(const PString & name, const PBYTEArray & octets);
683     virtual bool SetOptionOctets(const PString & name, const BYTE * data, PINDEX length);
684     virtual bool AddOption(OpalMediaOption * option, PBoolean overwrite = false);
685     virtual OpalMediaOption * FindOption(const PString & name) const;
686 
687     virtual bool ToNormalisedOptions();
688     virtual bool ToCustomisedOptions();
689     virtual bool Merge(const OpalMediaFormatInternal & mediaFormat);
690 
691     virtual bool ValidateMerge(const OpalMediaFormatInternal & mediaFormat) const;
692 
693     virtual bool IsValidForProtocol(const PString & protocol) const;
694 
695   protected:
696     PCaselessString              formatName;
697     RTP_DataFrame::PayloadTypes  rtpPayloadType;
698     PString                      rtpEncodingName;
699     OpalMediaType                mediaType;
700     PMutex                       media_format_mutex;
701     PSortedList<OpalMediaOption> options;
702     time_t                       codecVersionTime;
703     bool                         forceIsTransportable;
704     int                          m_channels;
705 
706   friend bool operator==(const char * other, const OpalMediaFormat & fmt);
707   friend bool operator!=(const char * other, const OpalMediaFormat & fmt);
708   friend bool operator==(const PString & other, const OpalMediaFormat & fmt);
709   friend bool operator!=(const PString & other, const OpalMediaFormat & fmt);
710 
711   friend class OpalMediaFormat;
712   friend class OpalMediaFormatList;
713   friend class OpalAudioFormatInternal;
714 };
715 
716 
717 ///////////////////////////////////////////////////////////////////////////////
718 
719 /**This class describes a media format as used in the OPAL system. A media
720    format is the type of any media data that is trasferred between OPAL
721    entities. For example an audio codec such as G.723.1 is a media format, a
722    video codec such as H.261 is also a media format.
723   */
724 class OpalMediaFormat : public PContainer
725 {
726     PCLASSINFO(OpalMediaFormat, PContainer)
727   public:
728     OpalMediaFormat(const OpalMediaFormat & c);
729     virtual ~OpalMediaFormat();
730     OpalMediaFormat & operator=(const OpalMediaFormat & c)     { AssignContents(c); return *this; }
731     virtual PBoolean MakeUnique();
732   protected:
733     virtual void DestroyContents();
734     virtual void AssignContents(const PContainer & c);
735 
736   public:
737     /**Default constructor creates a PCM-16 media format.
738       */
739     OpalMediaFormat(
740       OpalMediaFormatInternal * info = NULL
741     );
742 
743     /**This form of the constructor will register the full details of the
744        media format into an internal database. This would typically be used
745        as a static global. In fact it would be very dangerous for an instance
746        to use this constructor in any other way, especially local variables.
747 
748        If the rtpPayloadType is RTP_DataFrame::DynamicBase, then the RTP
749        payload type is actually set to the first unused dynamic RTP payload
750        type that is in the registers set of media formats.
751 
752        The frameSize parameter indicates that the media format has a maximum
753        size for each data frame, eg G.723.1 frames are no more than 24 bytes
754        long. If zero then there is no intrinsic maximum, eg G.711.
755       */
756     OpalMediaFormat(
757       const char * fullName,                      ///<  Full name of media format
758       const OpalMediaType & mediaType,            ///<  media type for this format
759       RTP_DataFrame::PayloadTypes rtpPayloadType, ///<  RTP payload type code
760       const char * encodingName,                  ///<  RTP encoding name
761       PBoolean     needsJitter,                   ///<  Indicate format requires a jitter buffer
762       unsigned bandwidth,                         ///<  Bandwidth in bits/second
763       PINDEX   frameSize,                         ///<  Size of frame in bytes (if applicable)
764       unsigned frameTime,                         ///<  Time for frame in RTP units (if applicable)
765       unsigned clockRate,                         ///<  Clock rate for data (if applicable)
766       time_t timeStamp = 0                        ///<  timestamp (for versioning)
767     );
768 
769     /**Construct a media format, searching database for information.
770        This constructor will search through the RegisteredMediaFormats list
771        for the match of the payload type, if found the other information
772        fields are set from the database. If not found then the ancestor
773        string is set to the empty string.
774 
775        Note it is impossible to determine the order of registration so this
776        should not be relied on.
777       */
778     OpalMediaFormat(
779       RTP_DataFrame::PayloadTypes rtpPayloadType, ///<  RTP payload type code
780       unsigned clockRate,                         ///<  clock rate
781       const char * rtpEncodingName = NULL,        ///<  RTP payload type name
782       const char * protocol = NULL                ///<  valid protocol (if NULL, then all)
783     );
784 
785     /**Construct a media format, searching database for information.
786        This constructor will search through the RegisteredMediaFormats list
787        for the wildcard match of the parameter string, if found the other
788        information fields are set from the database. If not found then the
789        ancestor string is set to the empty string.
790 
791        The wildcard string is a simple substring match using the '*'
792        character. For example: "G.711*" would match the first of
793        "G.711-uLaw-64k" and "G.711-ALaw-64k" to have been registered.
794 
795        Note it is impossible to determine the order of registration so this
796        should not be relied on.
797       */
798     OpalMediaFormat(
799       const char * wildcard  ///<  Wildcard name to search for
800     );
801 
802     /**Construct a media format, searching database for information.
803        This constructor will search through the RegisteredMediaFormats list
804        for the wildcard match of the parameter string, if found the other
805        information fields are set from the database. If not found then the
806        ancestor string is set to the empty string.
807 
808        The wildcard string is a simple substring match using the '*'
809        character. For example: "G.711*" would match the first of
810        "G.711-uLaw-64k" and "G.711-ALaw-64k" to have been registered.
811 
812        Note it is impossible to determine the order of registration so this
813        should not be relied on.
814       */
815     OpalMediaFormat(
816       const PString & wildcard  ///<  Wildcard name to search for
817     );
818 
819     /**Search for the specified format type.
820        This is equivalent to going fmt = OpalMediaFormat(rtpPayloadType);
821       */
822     OpalMediaFormat & operator=(
823       RTP_DataFrame::PayloadTypes rtpPayloadType ///<  RTP payload type code
824     );
825 
826     /**Search for the specified format name.
827        This is equivalent to going fmt = OpalMediaFormat(search);
828       */
829     OpalMediaFormat & operator=(
830       const char * wildcard  ///<  Wildcard name to search for
831     );
832 
833     /**Search for the specified format name.
834        This is equivalent to going fmt = OpalMediaFormat(search);
835       */
836     OpalMediaFormat & operator=(
837       const PString & wildcard  ///<  Wildcard name to search for
838     );
839 
840     /**Create a copy of the media format.
841       */
842     virtual PObject * Clone() const;
843 
844     /**Compare two media formats.
845       */
846     virtual Comparison Compare(const PObject & obj) const;
847 
848     /**Print media format.
849        Note if the user specifies a width (using setw() for example) of -1, then
850        a details multi-line output of all the options for the format is included.
851       */
852     virtual void PrintOn(ostream & strm) const;
853 
854     /**Read media format.
855       */
856     virtual void ReadFrom(istream & strm);
857 
858     /**This will translate the codec specific "custom" options to OPAL
859        "normalised" options, e.g. For H.261 "QCIF MPI"="1", "CIF MPI"="5"
860         would be translated to "Frame Width"="176", "Frame Height"="144".
861       */
862     bool ToNormalisedOptions();
863 
864     /**This will do the reverse of ToNormalisedOptions, translating the OPAL
865        "normalised" options to codec specific "custom" options.
866       */
867     bool ToCustomisedOptions();
868 
869     /**Update media format information.
870       */
871     bool Update(
872       const OpalMediaFormat & mediaFormat
873     );
874 
875     /**Merge with another media format. This will alter and validate
876        the options for this media format according to the merge rule for
877        each option. The parameter is typically a "capability" while the
878        current object isthe proposed channel format. This if the current
879        object has a tx number of frames of 3, but the parameter has a value
880        of 1, then the current object will be set to 1.
881 
882        Returns false if the media formats are incompatible and cannot be
883        merged.
884       */
885     bool Merge(
886       const OpalMediaFormat & mediaFormat
887     );
888     /**Return true if the given mediaFormat will successfully merge.
889       */
890     bool ValidateMerge(
891       const OpalMediaFormat & mediaFormat
892     ) const;
893 
894     /**Get the name of the format
895       */
GetName()896     PString GetName() const { PWaitAndSignal m(m_mutex); return m_info == NULL ? "" : m_info->formatName; }
897 
898     /**Return true if media format info is valid. This may be used if the
899        single string constructor is used to check that it matched something
900        in the registered media formats database.
901       */
IsValid()902     PBoolean IsValid() const { PWaitAndSignal m(m_mutex); return m_info != NULL && m_info->IsValid(); }
903 
904     /**Return true if media format info may be sent via RTP. Some formats are internal
905        use only and are never transported "over the wire".
906       */
IsTransportable()907     PBoolean IsTransportable() const { PWaitAndSignal m(m_mutex); return m_info != NULL && m_info->IsTransportable(); }
908 
909     /**Get the RTP payload type that is to be used for this media format.
910        This will either be an intrinsic one for the media format eg GSM or it
911        will be automatically calculated as a dynamic media format that will be
912        uniqueue amongst the registered media formats.
913       */
GetPayloadType()914     RTP_DataFrame::PayloadTypes GetPayloadType() const { PWaitAndSignal m(m_mutex); return m_info == NULL ? RTP_DataFrame::IllegalPayloadType : m_info->rtpPayloadType; }
SetPayloadType(RTP_DataFrame::PayloadTypes type)915     void SetPayloadType(RTP_DataFrame::PayloadTypes type) { PWaitAndSignal m(m_mutex); MakeUnique(); if (m_info != NULL) m_info->rtpPayloadType = type; }
916 
917     /**Get the RTP encoding name that is to be used for this media format.
918       */
GetEncodingName()919     const char * GetEncodingName() const { PWaitAndSignal m(m_mutex); return m_info == NULL ? "" : m_info->rtpEncodingName.GetPointer(); }
920 
921     /** Get the media type for this format
922       */
GetMediaType()923     OpalMediaType GetMediaType() const { PWaitAndSignal m(m_mutex); return m_info == NULL ? OpalMediaType() : m_info->mediaType; }
924 
925     /**Determine if the media format requires a jitter buffer. As a rule an
926        audio codec needs a jitter buffer and all others do not.
927       */
NeedsJitterBuffer()928     bool NeedsJitterBuffer() const { PWaitAndSignal m(m_mutex); return m_info != NULL && m_info->GetOptionBoolean(NeedsJitterOption(), false); }
929     static const PString & NeedsJitterOption();
930 
931     /**Get the average bandwidth used in bits/second.
932       */
GetBandwidth()933     unsigned GetBandwidth() const { PWaitAndSignal m(m_mutex); return m_info == NULL ? 0 : m_info->GetOptionInteger(MaxBitRateOption(), 0); }
934     static const PString & MaxBitRateOption();
935     static const PString & TargetBitRateOption();
936 
937     /**Get the maximum frame size in bytes. If this returns zero then the
938        media format has no intrinsic maximum frame size, eg a video format
939        would return zero but G.723.1 would return 24.
940       */
GetFrameSize()941     PINDEX GetFrameSize() const { PWaitAndSignal m(m_mutex); return m_info == NULL ? 0 : m_info->GetOptionInteger(MaxFrameSizeOption(), 0); }
942     static const PString & MaxFrameSizeOption();
943 
944     /**Get the frame time in RTP timestamp units. If this returns zero then
945        the media format is not real time and has no intrinsic timing eg T.120
946       */
GetFrameTime()947     unsigned GetFrameTime() const { PWaitAndSignal m(m_mutex); return m_info == NULL ? 0 : m_info->GetOptionInteger(FrameTimeOption(), 0); }
948     static const PString & FrameTimeOption();
949 
950     /**Get the number of RTP timestamp units per millisecond.
951       */
GetTimeUnits()952     unsigned GetTimeUnits() const { return GetClockRate()/1000; }
953 
954     enum StandardClockRate {
955       AudioClockRate = 8000,  ///<  8kHz sample rate
956       VideoClockRate = 90000  ///<  90kHz sample rate
957     };
958 
959     /**Get the clock rate in Hz for this format.
960       */
GetClockRate()961     unsigned GetClockRate() const { PWaitAndSignal m(m_mutex); return m_info == NULL ? 0 : m_info->GetOptionInteger(ClockRateOption(), 1000); }
962     static const PString & ClockRateOption();
963 
964     /**Get the name of the OpalMediaOption indicating the protocol the format is being used on.
965       */
966     static const PString & ProtocolOption();
967 
968     /**Get the name of the OpalMediaOption indicating the maximum RTP payload size.
969        Note this is a read only parameter and not generally set by the user. It
970        is intended to get the OpalManager::GetMaxRtpPayloadSize() value to the
971        codec (especially plug ins) before encoding starts in case the codec
972        requires some form of initialisation based on this value.
973       */
974     static const PString & MaxTxPacketSizeOption();
975 
976     /**Get all of the option values of the format as a dictionary.
977        Each entry is a name value pair.
978       */
GetOptions()979     PStringToString GetOptions() const { PWaitAndSignal m(m_mutex); return m_info == NULL ? PStringToString() : m_info->GetOptions(); }
980 
981     /**Get the number of options this media format has.
982       */
GetOptionCount()983     PINDEX GetOptionCount() const { PWaitAndSignal m(m_mutex); return m_info == NULL ? 0 : m_info->options.GetSize(); }
984 
985     /**Get the option instance at the specified index. This contains the
986        description and value for the option.
987       */
GetOption(PINDEX index)988     const OpalMediaOption & GetOption(
989       PINDEX index   ///<  Index of option in list to get
990     ) const { PWaitAndSignal m(m_mutex); return m_info->options[index]; }
991 
992     /**Get the option value of the specified name as a string.
993 
994        Returns false of the option is not present.
995       */
GetOptionValue(const PString & name,PString & value)996     bool GetOptionValue(
997       const PString & name,   ///<  Option name
998       PString & value         ///<  String to receive option value
999     ) const { PWaitAndSignal m(m_mutex); return m_info != NULL && m_info->GetOptionValue(name, value); }
1000 
1001     /**Set the option value of the specified name as a string.
1002        Note the option will not be added if it does not exist, the option
1003        must be explicitly added using AddOption().
1004 
1005        Returns false of the option is not present.
1006       */
SetOptionValue(const PString & name,const PString & value)1007     bool SetOptionValue(
1008       const PString & name,   ///<  Option name
1009       const PString & value   ///<  New option value as string
1010     ) { PWaitAndSignal m(m_mutex); MakeUnique(); return m_info != NULL && m_info->SetOptionValue(name, value); }
1011 
1012     /**Get the option value of the specified name as a boolean. The default
1013        value is returned if the option is not present.
1014       */
1015     bool GetOptionBoolean(
1016       const PString & name,   ///<  Option name
1017       bool dflt = false       ///<  Default value if option not present
1018     ) const { PWaitAndSignal m(m_mutex); return m_info != NULL && m_info->GetOptionBoolean(name, dflt); }
1019 
1020     /**Set the option value of the specified name as a boolean.
1021        Note the option will not be added if it does not exist, the option
1022        must be explicitly added using AddOption().
1023 
1024        Returns false of the option is not present or is not of the same type.
1025       */
SetOptionBoolean(const PString & name,bool value)1026     bool SetOptionBoolean(
1027       const PString & name,   ///<  Option name
1028       bool value              ///<  New value for option
1029     ) { PWaitAndSignal m(m_mutex); MakeUnique(); return m_info != NULL && m_info->SetOptionBoolean(name, value); }
1030 
1031     /**Get the option value of the specified name as an integer. The default
1032        value is returned if the option is not present.
1033       */
1034     int GetOptionInteger(
1035       const PString & name,   ///<  Option name
1036       int dflt = 0            ///<  Default value if option not present
1037     ) const { PWaitAndSignal m(m_mutex); return m_info == NULL ? dflt : m_info->GetOptionInteger(name, dflt); }
1038 
1039     /**Set the option value of the specified name as an integer.
1040        Note the option will not be added if it does not exist, the option
1041        must be explicitly added using AddOption().
1042 
1043        Returns false of the option is not present, not of the same type or
1044        is putside the allowable range.
1045       */
SetOptionInteger(const PString & name,int value)1046     bool SetOptionInteger(
1047       const PString & name,   ///<  Option name
1048       int value               ///<  New value for option
1049     ) { PWaitAndSignal m(m_mutex); MakeUnique(); return m_info != NULL && m_info->SetOptionInteger(name, value); }
1050 
1051     /**Get the option value of the specified name as a real. The default
1052        value is returned if the option is not present.
1053       */
1054     double GetOptionReal(
1055       const PString & name,   ///<  Option name
1056       double dflt = 0         ///<  Default value if option not present
1057     ) const { PWaitAndSignal m(m_mutex); return m_info == NULL ? dflt : m_info->GetOptionReal(name, dflt); }
1058 
1059     /**Set the option value of the specified name as a real.
1060        Note the option will not be added if it does not exist, the option
1061        must be explicitly added using AddOption().
1062 
1063        Returns false of the option is not present or is not of the same type.
1064       */
SetOptionReal(const PString & name,double value)1065     bool SetOptionReal(
1066       const PString & name,   ///<  Option name
1067       double value            ///<  New value for option
1068     ) { PWaitAndSignal m(m_mutex); MakeUnique(); return m_info != NULL && m_info->SetOptionReal(name, value); }
1069 
1070     /**Get the option value of the specified name as an index into an
1071        enumeration list. The default value is returned if the option is not
1072        present.
1073       */
1074     PINDEX GetOptionEnum(
1075       const PString & name,   ///<  Option name
1076       PINDEX dflt = 0         ///<  Default value if option not present
1077     ) const { PWaitAndSignal m(m_mutex); return m_info == NULL ? dflt : m_info->GetOptionEnum(name, dflt); }
1078 
1079     /**Set the option value of the specified name as an index into an enumeration.
1080        Note the option will not be added if it does not exist, the option
1081        must be explicitly added using AddOption().
1082 
1083        Returns false of the option is not present or is not of the same type.
1084       */
SetOptionEnum(const PString & name,PINDEX value)1085     bool SetOptionEnum(
1086       const PString & name,   ///<  Option name
1087       PINDEX value            ///<  New value for option
1088     ) { PWaitAndSignal m(m_mutex); MakeUnique(); return m_info != NULL && m_info->SetOptionEnum(name, value); }
1089 
1090     /**Get the option value of the specified name as a string. The default
1091        value is returned if the option is not present.
1092       */
1093     PString GetOptionString(
1094       const PString & name,                   ///<  Option name
1095       const PString & dflt = PString::Empty() ///<  Default value if option not present
1096     ) const { PWaitAndSignal m(m_mutex); return m_info == NULL ? dflt : m_info->GetOptionString(name, dflt); }
1097 
1098     /**Set the option value of the specified name as a string.
1099        Note the option will not be added if it does not exist, the option
1100        must be explicitly added using AddOption().
1101 
1102        Returns false of the option is not present or is not of the same type.
1103       */
SetOptionString(const PString & name,const PString & value)1104     bool SetOptionString(
1105       const PString & name,   ///<  Option name
1106       const PString & value   ///<  New value for option
1107     ) { PWaitAndSignal m(m_mutex); MakeUnique(); return m_info != NULL && m_info->SetOptionString(name, value); }
1108 
1109     /**Get the option value of the specified name as an octet array.
1110        Returns false if not present.
1111       */
GetOptionOctets(const PString & name,PBYTEArray & octets)1112     bool GetOptionOctets(
1113       const PString & name, ///<  Option name
1114       PBYTEArray & octets   ///<  Octets in option
1115     ) const { PWaitAndSignal m(m_mutex); return m_info != NULL && m_info->GetOptionOctets(name, octets); }
1116 
1117     /**Set the option value of the specified name as an octet array.
1118        Note the option will not be added if it does not exist, the option
1119        must be explicitly added using AddOption().
1120 
1121        Returns false of the option is not present or is not of the same type.
1122       */
SetOptionOctets(const PString & name,const PBYTEArray & octets)1123     bool SetOptionOctets(
1124       const PString & name,       ///<  Option name
1125       const PBYTEArray & octets   ///<  Octets in option
1126     ) { PWaitAndSignal m(m_mutex); MakeUnique(); return m_info != NULL && m_info->SetOptionOctets(name, octets); }
SetOptionOctets(const PString & name,const BYTE * data,PINDEX length)1127     bool SetOptionOctets(
1128       const PString & name,       ///<  Option name
1129       const BYTE * data,          ///<  Octets in option
1130       PINDEX length               ///<  Number of octets
1131     ) { PWaitAndSignal m(m_mutex); MakeUnique(); return m_info != NULL && m_info->SetOptionOctets(name, data, length); }
1132 
1133     /**Get a copy of the list of media formats that have been registered.
1134       */
1135     static OpalMediaFormatList GetAllRegisteredMediaFormats();
1136     static void GetAllRegisteredMediaFormats(
1137       OpalMediaFormatList & copy    ///<  List to receive the copy of the master list
1138     );
1139 
1140     /**Set the options on the master format list entry.
1141        The media format must already be registered. Returns false if not.
1142       */
1143     static bool SetRegisteredMediaFormat(
1144       const OpalMediaFormat & mediaFormat  ///<  Media format to copy to master list
1145     );
1146 
1147     /**Remove the media format from master format list entry.
1148        The media format must already be registered. Returns false if not.
1149       */
1150     static bool RemoveRegisteredMediaFormat(
1151       const OpalMediaFormat & mediaFormat  ///<  Media format to copy to master list
1152     );
1153 
1154     /**
1155       * Add a new option to this media format
1156       */
1157     bool AddOption(
1158       OpalMediaOption * option,
1159       PBoolean overwrite = false
1160     ) { PWaitAndSignal m(m_mutex); MakeUnique(); return m_info != NULL && m_info->AddOption(option, overwrite); }
1161 
1162     /**
1163       * Determine if media format has the specified option.
1164       */
HasOption(const PString & name)1165     bool HasOption(const PString & name) const { PWaitAndSignal m(m_mutex); return m_info != NULL && m_info->FindOption(name) != NULL; }
1166 
1167     /** Get a pointer to the specified media format option.
1168         Returns NULL if thee option does not exist.
1169       */
FindOption(const PString & name)1170     OpalMediaOption * FindOption(
1171       const PString & name
1172     ) const { PWaitAndSignal m(m_mutex); return m_info == NULL ? NULL : m_info->FindOption(name); }
1173 
1174     /** Get a pointer to the specified media format option.
1175         Returns NULL if thee option does not exist.
1176       */
FindOptionAs(const PString & name)1177     template <class T> T * FindOptionAs(
1178       const PString & name
1179     ) const { return dynamic_cast<T *>(FindOption(name)); }
1180 
1181     /** Returns true if the media format is valid for the protocol specified
1182         This allow plugin codecs to customise which protocols they are valid for
1183         The default implementation returns true unless the protocol is H.323
1184         and the rtpEncodingName is NULL
1185       */
IsValidForProtocol(const PString & protocol)1186     bool IsValidForProtocol(const PString & protocol) const { PWaitAndSignal m(m_mutex); return m_info != NULL && m_info->IsValidForProtocol(protocol); }
1187 
GetCodecVersionTime()1188     time_t GetCodecVersionTime() const { PWaitAndSignal m(m_mutex); return m_info == NULL ? 0 : m_info->codecVersionTime; }
1189 
PrintOptions(ostream & strm)1190     ostream & PrintOptions(ostream & strm) const
1191     {
1192       PWaitAndSignal m(m_mutex);
1193       if (m_info != NULL)
1194         strm << setw(-1) << *m_info;
1195       return strm;
1196     }
1197 
1198 #if OPAL_VIDEO
1199     /** Adjust the video device arguments from the media format.
1200      */
1201     void AdjustVideoArgs(
1202       PVideoDevice::OpenArgs & args  /// Videoo device arguments to adjust
1203     ) const;
1204 #endif
1205 
1206     // Backward compatibility
IsEmpty()1207     virtual PBoolean IsEmpty() const { PWaitAndSignal m(m_mutex); return m_info == NULL || !m_info->IsValid(); }
PString()1208     operator PString() const { PWaitAndSignal m(m_mutex); return m_info == NULL ? "" : m_info->formatName; }
1209     operator const char *() const { PWaitAndSignal m(m_mutex); return m_info == NULL ? "" : m_info->formatName; }
1210     bool operator==(const char * other) const { PWaitAndSignal m(m_mutex); return m_info != NULL && m_info->formatName == other; }
1211     bool operator!=(const char * other) const { PWaitAndSignal m(m_mutex); return m_info == NULL || m_info->formatName != other; }
1212     bool operator==(const PString & other) const { PWaitAndSignal m(m_mutex); return m_info != NULL && m_info->formatName == other; }
1213     bool operator!=(const PString & other) const { PWaitAndSignal m(m_mutex); return m_info == NULL || m_info->formatName != other; }
1214     bool operator==(const OpalMediaFormat & other) const { PWaitAndSignal m(m_mutex); return Compare(other) == EqualTo; }
1215     bool operator!=(const OpalMediaFormat & other) const { PWaitAndSignal m(m_mutex); return Compare(other) != EqualTo; }
1216     friend bool operator==(const char * other, const OpalMediaFormat & fmt) { return fmt.m_info != NULL && fmt.m_info->formatName == other; }
1217     friend bool operator!=(const char * other, const OpalMediaFormat & fmt) { return fmt.m_info == NULL || fmt.m_info->formatName != other; }
1218     friend bool operator==(const PString & other, const OpalMediaFormat & fmt) { return fmt.m_info != NULL && fmt.m_info->formatName == other; }
1219     friend bool operator!=(const PString & other, const OpalMediaFormat & fmt) { return fmt.m_info == NULL || fmt.m_info->formatName != other; }
1220 
1221 #if OPAL_H323
1222     static const PString & MediaPacketizationOption();
1223     static const PString & MediaPacketizationsOption();
1224     PStringSet GetMediaPacketizations() const;
1225     void SetMediaPacketizations(const PStringSet & packetizations);
1226 #endif
1227 
1228   private:
SetSize(PINDEX)1229     PBoolean SetSize(PINDEX) { return true; }
1230 
1231   protected:
1232     void Construct(OpalMediaFormatInternal * info);
1233 
1234     OpalMediaFormatInternal * m_info;
1235     PMutex                    m_mutex;
1236 
1237   friend class OpalMediaFormatInternal;
1238   friend class OpalMediaFormatList;
1239 };
1240 
1241 
1242 class OpalAudioFormatInternal : public OpalMediaFormatInternal
1243 {
1244   public:
1245     OpalAudioFormatInternal(
1246       const char * fullName,
1247       RTP_DataFrame::PayloadTypes rtpPayloadType,
1248       const char * encodingName,
1249       PINDEX   frameSize,
1250       unsigned frameTime,
1251       unsigned rxFrames,
1252       unsigned txFrames,
1253       unsigned maxFrames,
1254       unsigned clockRate,
1255       time_t timeStamp
1256     );
1257     virtual PObject * Clone() const;
1258     virtual bool Merge(const OpalMediaFormatInternal & mediaFormat);
1259 };
1260 
1261 class OpalAudioFormat : public OpalMediaFormat
1262 {
1263     PCLASSINFO(OpalAudioFormat, OpalMediaFormat);
1264   public:
1265     OpalAudioFormat(
1266       OpalMediaFormatInternal * info = NULL
OpalMediaFormat(info)1267     ) : OpalMediaFormat(info) { }
1268     OpalAudioFormat(
1269       const char * fullName,    ///<  Full name of media format
1270       RTP_DataFrame::PayloadTypes rtpPayloadType, ///<  RTP payload type code
1271       const char * encodingName,///<  RTP encoding name
1272       PINDEX   frameSize,       ///<  Size of frame in bytes (if applicable)
1273       unsigned frameTime,       ///<  Time for frame in RTP units (if applicable)
1274       unsigned rxFrames,        ///<  Maximum number of frames per packet we can receive
1275       unsigned txFrames,        ///<  Desired number of frames per packet we transmit
1276       unsigned maxFrames = 256, ///<  Maximum possible frames per packet
1277       unsigned clockRate = 8000, ///<  Clock Rate
1278       time_t timeStamp = 0       ///<  timestamp (for versioning)
1279     );
1280 
1281     static const PString & RxFramesPerPacketOption();
1282     static const PString & TxFramesPerPacketOption();
1283     static const PString & MaxFramesPerPacketOption();
1284     static const PString & ChannelsOption();
1285 };
1286 
1287 #if OPAL_VIDEO
1288 class OpalVideoFormatInternal : public OpalMediaFormatInternal
1289 {
1290   public:
1291     OpalVideoFormatInternal(
1292       const char * fullName,
1293       RTP_DataFrame::PayloadTypes rtpPayloadType,
1294       const char * encodingName,
1295       unsigned maxFrameWidth,
1296       unsigned maxFrameHeight,
1297       unsigned maxFrameRate,
1298       unsigned maxBitRate,
1299       time_t timeStamp
1300     );
1301     virtual PObject * Clone() const;
1302     virtual bool Merge(const OpalMediaFormatInternal & mediaFormat);
1303 };
1304 
1305 
1306 class OpalVideoFormat : public OpalMediaFormat
1307 {
1308     PCLASSINFO(OpalVideoFormat, OpalMediaFormat);
1309   public:
1310     OpalVideoFormat(
1311       OpalMediaFormatInternal * info = NULL
OpalMediaFormat(info)1312     ) : OpalMediaFormat(info) { }
1313     OpalVideoFormat(
1314       const char * fullName,    ///<  Full name of media format
1315       RTP_DataFrame::PayloadTypes rtpPayloadType, ///<  RTP payload type code
1316       const char * encodingName,///<  RTP encoding name
1317       unsigned maxFrameWidth,   ///<  Width of video frame
1318       unsigned maxFrameHeight,  ///<  Height of video frame
1319       unsigned maxFrameRate,    ///<  Number of frames per second
1320       unsigned maxBitRate,      ///<  Maximum bits per second
1321       time_t timeStamp = 0      ///<  timestamp (for versioning)
1322     );
1323 
1324     static const PString & FrameWidthOption();
1325     static const PString & FrameHeightOption();
1326     static const PString & MinRxFrameWidthOption();
1327     static const PString & MinRxFrameHeightOption();
1328     static const PString & MaxRxFrameWidthOption();
1329     static const PString & MaxRxFrameHeightOption();
1330     static const PString & TemporalSpatialTradeOffOption();
1331     static const PString & TxKeyFramePeriodOption();
1332     static const PString & RateControlPeriodOption(); // Period over which the rate controller maintains the target bit rate.
1333     static const PString & RateControllerOption(); // String for controller algorithm. Empty is none.
1334 
1335     /**The "role" of the content in the video stream based on this media
1336        format. This is based on RFC4796 and H.239 semantics and is an
1337        enumeration consisting of:
1338           Value          H.239                RFC4796
1339           NoRole         Not used             (not populated)
1340           Presentation   Presentation (0x01)  slides
1341           Main           Live (0x02)          main
1342           Speaker        Live (0x02)          speaker
1343           SignLanguage   Live (0x02)          sl
1344       */
1345     enum ContentRole {
1346       eNoRole,
1347       ePresentation,
1348       eMainRole,
1349       eSpeaker,
1350       eSignLanguage,
1351       eNumRoles
1352     };
1353     enum { ContentRoleMask = 15 };
ContentRoleBit(ContentRole contentRole)1354     __inline static unsigned ContentRoleBit(ContentRole contentRole) { return contentRole != eNoRole ? (1<<(contentRole-1)) : 0; }
1355     static const PString & ContentRoleOption();
1356     static const PString & ContentRoleMaskOption();
1357 };
1358 #endif
1359 
1360 // List of known media formats
1361 
1362 #define OPAL_PCM16          "PCM-16"
1363 #define OPAL_PCM16S         "PCM-16S"
1364 #define OPAL_PCM16_16KHZ    "PCM-16-16kHz"
1365 #define OPAL_PCM16S_16KHZ   "PCM-16S-16kHz"
1366 #define OPAL_PCM16_32KHZ    "PCM-16-32kHz"
1367 #define OPAL_PCM16S_32KHZ   "PCM-16S-32kHz"
1368 #define OPAL_PCM16_48KHZ    "PCM-16-48kHz"
1369 #define OPAL_PCM16S_48KHZ   "PCM-16S-48kHz"
1370 #define OPAL_L16_MONO_8KHZ  "Linear-16-Mono-8kHz"
1371 #define OPAL_L16_STEREO_8KHZ "Linear-16-Stereo-8kHz"
1372 #define OPAL_L16_MONO_16KHZ "Linear-16-Mono-16kHz"
1373 #define OPAL_L16_STEREO_16KHZ "Linear-16-Stereo-16kHz"
1374 #define OPAL_L16_MONO_32KHZ "Linear-16-Mono-32kHz"
1375 #define OPAL_L16_STEREO_32KHZ "Linear-16-Stereo-32kHz"
1376 #define OPAL_L16_MONO_48KHZ "Linear-16-Mono-48kHz"
1377 #define OPAL_L16_STEREO_48KHZ "Linear-16-Stereo-48kHz"
1378 #define OPAL_G711_ULAW_64K  "G.711-uLaw-64k"
1379 #define OPAL_G711_ALAW_64K  "G.711-ALaw-64k"
1380 #define OPAL_G722           "G.722"
1381 #define OPAL_G7221          "G.722.1"
1382 #define OPAL_G7222          "G.722.2"
1383 #define OPAL_G726_40K       "G.726-40K"
1384 #define OPAL_G726_32K       "G.726-32K"
1385 #define OPAL_G726_24K       "G.726-24K"
1386 #define OPAL_G726_16K       "G.726-16K"
1387 #define OPAL_G728           "G.728"
1388 #define OPAL_G729           "G.729"
1389 #define OPAL_G729A          "G.729A"
1390 #define OPAL_G729B          "G.729B"
1391 #define OPAL_G729AB         "G.729A/B"
1392 #define OPAL_G7231          "G.723.1"
1393 #define OPAL_G7231_6k3      OPAL_G7231
1394 #define OPAL_G7231_5k3      "G.723.1(5.3k)"
1395 #define OPAL_G7231A_6k3     "G.723.1A(6.3k)"
1396 #define OPAL_G7231A_5k3     "G.723.1A(5.3k)"
1397 #define OPAL_GSM0610        "GSM-06.10"
1398 #define OPAL_GSMAMR         "GSM-AMR"
1399 #define OPAL_iLBC           "iLBC"
1400 #define OPAL_H261           "H.261"
1401 #define OPAL_H263           "H.263"
1402 #define OPAL_H264           "H.264"
1403 #define OPAL_H264_MODE0     "H.264-0"
1404 #define OPAL_H264_MODE1     "H.264-1"
1405 #define OPAL_MPEG4          "MPEG4"
1406 #define OPAL_RFC2833        "UserInput/RFC2833"
1407 #define OPAL_CISCONSE       "NamedSignalEvent"
1408 #define OPAL_T38            "T.38"
1409 
1410 extern const OpalAudioFormat & GetOpalPCM16();
1411 extern const OpalAudioFormat & GetOpalPCM16S();
1412 extern const OpalAudioFormat & GetOpalPCM16_16KHZ();
1413 extern const OpalAudioFormat & GetOpalPCM16S_16KHZ();
1414 extern const OpalAudioFormat & GetOpalPCM16_32KHZ();
1415 extern const OpalAudioFormat & GetOpalPCM16S_32KHZ();
1416 extern const OpalAudioFormat & GetOpalPCM16_48KHZ();
1417 extern const OpalAudioFormat & GetOpalPCM16S_48KHZ();
1418 extern const OpalAudioFormat & GetOpalL16_MONO_8KHZ();
1419 extern const OpalAudioFormat & GetOpalL16_STEREO_8KHZ();
1420 extern const OpalAudioFormat & GetOpalL16_MONO_16KHZ();
1421 extern const OpalAudioFormat & GetOpalL16_STEREO_16KHZ();
1422 extern const OpalAudioFormat & GetOpalL16_MONO_32KHZ();
1423 extern const OpalAudioFormat & GetOpalL16_STEREO_32KHZ();
1424 extern const OpalAudioFormat & GetOpalL16_MONO_48KHZ();
1425 extern const OpalAudioFormat & GetOpalL16_STEREO_48KHZ();
1426 extern const OpalAudioFormat & GetOpalG711_ULAW_64K();
1427 extern const OpalAudioFormat & GetOpalG711_ALAW_64K();
1428 extern const OpalAudioFormat & GetOpalG722();
1429 extern const OpalAudioFormat & GetOpalG7221();
1430 extern const OpalAudioFormat & GetOpalG7222();
1431 extern const OpalAudioFormat & GetOpalG726_40K();
1432 extern const OpalAudioFormat & GetOpalG726_32K();
1433 extern const OpalAudioFormat & GetOpalG726_24K();
1434 extern const OpalAudioFormat & GetOpalG726_16K();
1435 extern const OpalAudioFormat & GetOpalG728();
1436 extern const OpalAudioFormat & GetOpalG729();
1437 extern const OpalAudioFormat & GetOpalG729A();
1438 extern const OpalAudioFormat & GetOpalG729B();
1439 extern const OpalAudioFormat & GetOpalG729AB();
1440 extern const OpalAudioFormat & GetOpalG7231_6k3();
1441 extern const OpalAudioFormat & GetOpalG7231_5k3();
1442 extern const OpalAudioFormat & GetOpalG7231A_6k3();
1443 extern const OpalAudioFormat & GetOpalG7231A_5k3();
1444 extern const OpalAudioFormat & GetOpalGSM0610();
1445 extern const OpalAudioFormat & GetOpalGSMAMR();
1446 extern const OpalAudioFormat & GetOpaliLBC();
1447 
1448 extern const OpalMediaFormat & GetOpalRFC2833();
1449 
1450 #if OPAL_T38_CAPABILITY
1451 extern const OpalMediaFormat & GetOpalCiscoNSE();
1452 extern const OpalMediaFormat & GetOpalT38();
1453 #endif
1454 
1455 
1456 #define OpalPCM16          GetOpalPCM16()
1457 #define OpalPCM16S         GetOpalPCM16S()
1458 #define OpalPCM16_16KHZ    GetOpalPCM16_16KHZ()
1459 #define OpalPCM16S_16KHZ   GetOpalPCM16S_16KHZ()
1460 #define OpalPCM16_32KHZ    GetOpalPCM16_32KHZ()
1461 #define OpalPCM16S_32KHZ   GetOpalPCM16S_32KHZ()
1462 #define OpalPCM16_48KHZ    GetOpalPCM16_48KHZ()
1463 #define OpalPCM16S_48KHZ   GetOpalPCM16S_48KHZ()
1464 #define OpalL16_MONO_8KHZ  GetOpalL16_MONO_8KHZ()
1465 #define OpalL16_STEREO_8KHZ GetOpalL16_STEREO_8KHZ()
1466 #define OpalL16_MONO_16KHZ GetOpalL16_MONO_16KHZ()
1467 #define OpalL16_STEREO_16KHZ GetOpalL16_STEREO_16KHZ()
1468 #define OpalL16_MONO_32KHZ GetOpalL16_MONO_32KHZ()
1469 #define OpalL16_STEREO_32KHZ GetOpalL16_STEREO_32KHZ()
1470 #define OpalL16_MONO_48KHZ GetOpalL16_MONO_48KHZ()
1471 #define OpalL16_STEREO_48KHZ GetOpalL16_STEREO_48KHZ()
1472 #define OpalG711_ULAW_64K  GetOpalG711_ULAW_64K()
1473 #define OpalG711_ALAW_64K  GetOpalG711_ALAW_64K()
1474 #define OpalG722           GetOpalG722()
1475 #define OpalG7221          GetOpalG7221()
1476 #define OpalG7222          GetOpalG7222()
1477 #define OpalG726_40K       GetOpalG726_40K()
1478 #define OpalG726_32K       GetOpalG726_32K()
1479 #define OpalG726_24K       GetOpalG726_24K()
1480 #define OpalG726_16K       GetOpalG726_16K()
1481 #define OpalG728           GetOpalG728()
1482 #define OpalG729           GetOpalG729()
1483 #define OpalG729A          GetOpalG729A()
1484 #define OpalG729B          GetOpalG729B()
1485 #define OpalG729AB         GetOpalG729AB()
1486 #define OpalG7231_6k3      GetOpalG7231_6k3()
1487 #define OpalG7231_5k3      GetOpalG7231_5k3()
1488 #define OpalG7231A_6k3     GetOpalG7231A_6k3()
1489 #define OpalG7231A_5k3     GetOpalG7231A_5k3()
1490 #define OpalGSM0610        GetOpalGSM0610()
1491 #define OpalGSMAMR         GetOpalGSMAMR()
1492 #define OpaliLBC           GetOpaliLBC()
1493 #define OpalRFC2833        GetOpalRFC2833()
1494 #define OpalCiscoNSE       GetOpalCiscoNSE()
1495 #define OpalT38            GetOpalT38()
1496 
1497 #define OpalL16Mono8kHz    OpalL16_MONO_8KHZ
1498 #define OpalL16Mono16kHz   OpalL16_MONO_16KHZ
1499 #define OpalG711uLaw       OpalG711_ULAW_64K
1500 #define OpalG711ALaw       OpalG711_ALAW_64K
1501 
1502 #define OPAL_T140             "T.140"
1503 #define OpalT140              GetOpalT140()
1504 extern const OpalMediaFormat & GetOpalT140();
1505 
1506 #if OPAL_HAS_MSRP
1507 #define OPAL_MSRP           "MSRP"
1508 #define OpalMSRP            GetOpalMSRP()
1509 extern const OpalMediaFormat & GetOpalMSRP();
1510 #endif
1511 
1512 #if OPAL_HAS_SIPIM
1513 #define OPAL_SIPIM             "SIP-IM"
1514 #define OpalSIPIM              GetOpalSIPIM()
1515 extern const OpalMediaFormat & GetOpalSIPIM();
1516 #endif
1517 
1518 #ifdef _MSC_VER
1519 #if _MSC_VER < 1300
1520 #pragma warning(default:4663)
1521 #endif
1522 #endif
1523 
1524 #endif  // OPAL_OPAL_MEDIAFMT_H
1525 
1526 
1527 // End of File ///////////////////////////////////////////////////////////////
1528