1/* 2 * Python bindings. 3 * 4 * Open Phone Abstraction Library (OPAL) 5 * 6 * Copyright (c) 2011 Demetrius Cassidy 7 * 8 * The contents of this file are subject to the Mozilla Public License 9 * Version 1.0 (the "License"); you may not use this file except in 10 * compliance with the License. You may obtain a copy of the License at 11 * http://www.mozilla.org/MPL/ 12 * 13 * Software distributed under the License is distributed on an "AS IS" 14 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 15 * the License for the specific language governing rights and limitations 16 * under the License. 17 * 18 * The Original Code is Open Phone Abstraction Library (OPAL) 19 * 20 * The Initial Developer of the Original Code is Demetrius Cassidy 21 * 22 * Contributor(s): ______________________________________. 23 * 24 * $Revision: 26570 $ 25 * $Author: rjongbloed $ 26 * $Date: 2011-10-09 20:00:46 -0500 (Sun, 09 Oct 2011) $ 27 */ 28 29/////////////////////////////////////////////////////////////////////////////// 30 31/**Base class for options attached to an OpalMediaFormat. 32 */ 33class OpalMediaOption : PObject /Abstract/ 34{ 35%TypeHeaderCode 36#include <ptlib.h> 37#include <opal/mediafmt.h> 38%End 39 40 public: 41 enum MergeType { 42 NoMerge, 43 MinMerge, 44 MaxMerge, 45 EqualMerge, 46 NotEqualMerge, 47 AlwaysMerge, 48 49 // Synonyms 50 AndMerge = MinMerge, 51 OrMerge = MaxMerge 52 }; 53 54 protected: 55 OpalMediaOption( 56 const PString & name 57 ); 58 OpalMediaOption( 59 const char * name, 60 bool readOnly, 61 MergeType merge 62 ); 63 64 public: 65 virtual Comparison Compare(const PObject & obj) const; 66 67 virtual bool Merge( 68 const OpalMediaOption & option 69 ); 70 virtual Comparison CompareValue( 71 const OpalMediaOption & option 72 ) const = 0; 73 virtual void Assign( 74 const OpalMediaOption & option 75 ) = 0; 76 77 PString AsString() const; 78 bool FromString(const PString & value); 79 80 const PString & GetName() const; 81 82 bool IsReadOnly() const; 83 void SetReadOnly(bool readOnly); 84 85 MergeType GetMerge() const; 86 void SetMerge(MergeType merge); 87 88 const PString & GetFMTPName() const; 89 void SetFMTPName(const char * name); 90 91 const PString & GetFMTPDefault() const; 92 void SetFMTPDefault(const char * value); 93 94 95 struct H245GenericInfo { 96 H245GenericInfo(); 97 unsigned ordinal; 98 99 enum Modes { 100 None, 101 Collapsing, 102 NonCollapsing 103 }; 104 105 enum IntegerTypes { 106 UnsignedInt, 107 Unsigned32, 108 BooleanArray 109 }; 110 111 bool excludeTCS; 112 bool excludeOLC; 113 bool excludeReqMode; 114 }; 115 116 const H245GenericInfo & GetH245Generic() const; 117 void SetH245Generic(const H245GenericInfo & genericInfo); 118 119}; 120 121/////////////////////////////////////////////////////////////////////////////// 122 123/**This class describes a media format as used in the OPAL system. A media 124 format is the type of any media data that is trasferred between OPAL 125 entities. For example an audio codec such as G.723.1 is a media format, a 126 video codec such as H.261 is also a media format. 127 */ 128class OpalMediaFormat : PContainer 129{ 130 131%TypeHeaderCode 132#include <ptlib.h> 133#include <opal/mediafmt.h> 134%End 135 136 public: 137 /**This form of the constructor will register the full details of the 138 media format into an internal database. This would typically be used 139 as a static global. In fact it would be very dangerous for an instance 140 to use this constructor in any other way, especially local variables. 141 142 If the rtpPayloadType is RTP_DataFrame::DynamicBase, then the RTP 143 payload type is actually set to the first unused dynamic RTP payload 144 type that is in the registers set of media formats. 145 146 The frameSize parameter indicates that the media format has a maximum 147 size for each data frame, eg G.723.1 frames are no more than 24 bytes 148 long. If zero then there is no intrinsic maximum, eg G.711. 149 */ 150 OpalMediaFormat( 151 const char * fullName, ///< Full name of media format 152 const OpalMediaType & mediaType, ///< media type for this format 153 RTP_DataFrame::PayloadTypes rtpPayloadType, ///< RTP payload type code 154 const char * encodingName, ///< RTP encoding name 155 PBoolean needsJitter, ///< Indicate format requires a jitter buffer 156 unsigned bandwidth, ///< Bandwidth in bits/second 157 PINDEX frameSize, ///< Size of frame in bytes (if applicable) 158 unsigned frameTime, ///< Time for frame in RTP units (if applicable) 159 unsigned clockRate, ///< Clock rate for data (if applicable) 160 time_t timeStamp = 0 ///< timestamp (for versioning) 161 ); 162 163 /**Construct a media format, searching database for information. 164 This constructor will search through the RegisteredMediaFormats list 165 for the match of the payload type, if found the other information 166 fields are set from the database. If not found then the ancestor 167 string is set to the empty string. 168 169 Note it is impossible to determine the order of registration so this 170 should not be relied on. 171 */ 172 OpalMediaFormat( 173 RTP_DataFrame::PayloadTypes rtpPayloadType, ///< RTP payload type code 174 unsigned clockRate, ///< clock rate 175 const char * rtpEncodingName = NULL, ///< RTP payload type name 176 const char * protocol = NULL ///< valid protocol (if NULL, then all) 177 ); 178 179 /**Construct a media format, searching database for information. 180 This constructor will search through the RegisteredMediaFormats list 181 for the wildcard match of the parameter string, if found the other 182 information fields are set from the database. If not found then the 183 ancestor string is set to the empty string. 184 185 The wildcard string is a simple substring match using the '*' 186 character. For example: "G.711*" would match the first of 187 "G.711-uLaw-64k" and "G.711-ALaw-64k" to have been registered. 188 189 Note it is impossible to determine the order of registration so this 190 should not be relied on. 191 */ 192 OpalMediaFormat( 193 const char * wildcard ///< Wildcard name to search for 194 ); 195 196 /**Construct a media format, searching database for information. 197 This constructor will search through the RegisteredMediaFormats list 198 for the wildcard match of the parameter string, if found the other 199 information fields are set from the database. If not found then the 200 ancestor string is set to the empty string. 201 202 The wildcard string is a simple substring match using the '*' 203 character. For example: "G.711*" would match the first of 204 "G.711-uLaw-64k" and "G.711-ALaw-64k" to have been registered. 205 206 Note it is impossible to determine the order of registration so this 207 should not be relied on. 208 */ 209 OpalMediaFormat( 210 const PString & wildcard ///< Wildcard name to search for 211 ); 212 213 214 /**Create a copy of the media format. 215 */ 216 virtual PObject * Clone() const; 217 218 /**Compare two media formats. 219 */ 220 virtual Comparison Compare(const PObject & obj) const; 221 222 /**This will translate the codec specific "custom" options to OPAL 223 "normalised" options, e.g. For H.261 "QCIF MPI"="1", "CIF MPI"="5" 224 would be translated to "Frame Width"="176", "Frame Height"="144". 225 */ 226 bool ToNormalisedOptions(); 227 228 /**This will do the reverse of ToNormalisedOptions, translating the OPAL 229 "normalised" options to codec specific "custom" options. 230 */ 231 bool ToCustomisedOptions(); 232 233 /**Merge with another media format. This will alter and validate 234 the options for this media format according to the merge rule for 235 each option. The parameter is typically a "capability" while the 236 current object isthe proposed channel format. This if the current 237 object has a tx number of frames of 3, but the parameter has a value 238 of 1, then the current object will be set to 1. 239 240 Returns PFalse if the media formats are incompatible and cannot be 241 merged. 242 */ 243 bool Merge( 244 const OpalMediaFormat & mediaFormat 245 ); 246 247 /**Get the name of the format 248 */ 249 PString GetName() const; 250 251 /**Return PTrue if media format info is valid. This may be used if the 252 single string constructor is used to check that it matched something 253 in the registered media formats database. 254 */ 255 PBoolean IsValid() const; 256 257 /**Return PTrue if media format info may be sent via RTP. Some formats are internal 258 use only and are never transported "over the wire". 259 */ 260 PBoolean IsTransportable() const; 261 262 /**Get the RTP payload type that is to be used for this media format. 263 This will either be an intrinsic one for the media format eg GSM or it 264 will be automatically calculated as a dynamic media format that will be 265 uniqueue amongst the registered media formats. 266 */ 267 RTP_DataFrame::PayloadTypes GetPayloadType() const; 268 void SetPayloadType(RTP_DataFrame::PayloadTypes type); 269 270 /**Get the RTP encoding name that is to be used for this media format. 271 */ 272 const char * GetEncodingName() const; 273 274 /** Get the media type for this format 275 */ 276 OpalMediaType GetMediaType() const; 277 278 /**Determine if the media format requires a jitter buffer. As a rule an 279 audio codec needs a jitter buffer and all others do not. 280 */ 281 bool NeedsJitterBuffer() const; 282 static const PString & NeedsJitterOption(); 283 284 /**Get the average bandwidth used in bits/second. 285 */ 286 unsigned GetBandwidth() const; 287 static const PString & MaxBitRateOption(); 288 static const PString & TargetBitRateOption(); 289 290 /**Get the maximum frame size in bytes. If this returns zero then the 291 media format has no intrinsic maximum frame size, eg a video format 292 would return zero but G.723.1 would return 24. 293 */ 294 PINDEX GetFrameSize() const; 295 static const PString & MaxFrameSizeOption(); 296 297 /**Get the frame time in RTP timestamp units. If this returns zero then 298 the media format is not real time and has no intrinsic timing eg T.120 299 */ 300 unsigned GetFrameTime() const; 301 static const PString & FrameTimeOption(); 302 303 /**Get the number of RTP timestamp units per millisecond. 304 */ 305 unsigned GetTimeUnits() const; 306 307 enum StandardClockRate { 308 AudioClockRate = 8000, ///< 8kHz sample rate 309 VideoClockRate = 90000 ///< 90kHz sample rate 310 }; 311 312 /**Get the clock rate in Hz for this format. 313 */ 314 unsigned GetClockRate() const; 315 static const PString & ClockRateOption(); 316 317 /**Get the name of the OpalMediaOption indicating the protocol the format is being used on. 318 */ 319 static const PString & ProtocolOption(); 320 321 /**Get the name of the OpalMediaOption indicating the maximum RTP payload size. 322 */ 323 static const PString & MaxTxPacketSizeOption(); 324 325 /**Get all of the option values of the format as a dictionary. 326 Each entry is a name value pair. 327 */ 328 PStringToString GetOptions() const; 329 330 /**Get the number of options this media format has. 331 */ 332 PINDEX GetOptionCount() const; 333 334 /**Get the option instance at the specified index. This contains the 335 description and value for the option. 336 */ 337 const OpalMediaOption & GetOption( 338 PINDEX index ///< Index of option in list to get 339 ) const; 340 341 /**Get the option value of the specified name as a string. 342 343 Returns false of the option is not present. 344 */ 345 bool GetOptionValue( 346 const PString & name, ///< Option name 347 PString & value /Out/ ///< String to receive option value 348 ) const; 349 350 /**Set the option value of the specified name as a string. 351 Note the option will not be added if it does not exist, the option 352 must be explicitly added using AddOption(). 353 354 Returns false of the option is not present. 355 */ 356 bool SetOptionValue( 357 const PString & name, ///< Option name 358 const PString & value ///< New option value as string 359 ); 360 361 /**Get the option value of the specified name as a boolean. The default 362 value is returned if the option is not present. 363 */ 364 bool GetOptionBoolean( 365 const PString & name, ///< Option name 366 bool dflt = PFalse ///< Default value if option not present 367 ) const; 368 369 /**Set the option value of the specified name as a boolean. 370 Note the option will not be added if it does not exist, the option 371 must be explicitly added using AddOption(). 372 373 Returns false of the option is not present or is not of the same type. 374 */ 375 bool SetOptionBoolean( 376 const PString & name, ///< Option name 377 bool value ///< New value for option 378 ); 379 380 /**Get the option value of the specified name as an integer. The default 381 value is returned if the option is not present. 382 */ 383 int GetOptionInteger( 384 const PString & name, ///< Option name 385 int dflt = 0 ///< Default value if option not present 386 ) const; 387 388 /**Set the option value of the specified name as an integer. 389 Note the option will not be added if it does not exist, the option 390 must be explicitly added using AddOption(). 391 392 Returns false of the option is not present, not of the same type or 393 is putside the allowable range. 394 */ 395 bool SetOptionInteger( 396 const PString & name, ///< Option name 397 int value ///< New value for option 398 ); 399 400 /**Get the option value of the specified name as a real. The default 401 value is returned if the option is not present. 402 */ 403 double GetOptionReal( 404 const PString & name, ///< Option name 405 double dflt = 0 ///< Default value if option not present 406 ) const; 407 408 /**Set the option value of the specified name as a real. 409 Note the option will not be added if it does not exist, the option 410 must be explicitly added using AddOption(). 411 412 Returns false of the option is not present or is not of the same type. 413 */ 414 bool SetOptionReal( 415 const PString & name, ///< Option name 416 double value ///< New value for option 417 ); 418 419 /**Get the option value of the specified name as an index into an 420 enumeration list. The default value is returned if the option is not 421 present. 422 */ 423 PINDEX GetOptionEnum( 424 const PString & name, ///< Option name 425 PINDEX dflt = 0 ///< Default value if option not present 426 ) const; 427 428 /**Set the option value of the specified name as an index into an enumeration. 429 Note the option will not be added if it does not exist, the option 430 must be explicitly added using AddOption(). 431 432 Returns false of the option is not present or is not of the same type. 433 */ 434 bool SetOptionEnum( 435 const PString & name, ///< Option name 436 PINDEX value ///< New value for option 437 ); 438 439 /**Get the option value of the specified name as a string. The default 440 value is returned if the option is not present. 441 */ 442 PString GetOptionString( 443 const PString & name, ///< Option name 444 const PString & dflt = PString::Empty() ///< Default value if option not present 445 ) const; 446 447 /**Set the option value of the specified name as a string. 448 Note the option will not be added if it does not exist, the option 449 must be explicitly added using AddOption(). 450 451 Returns false of the option is not present or is not of the same type. 452 */ 453 bool SetOptionString( 454 const PString & name, ///< Option name 455 const PString & value ///< New value for option 456 ); 457 458 /**Set the option value of the specified name as an octet array. 459 Note the option will not be added if it does not exist, the option 460 must be explicitly added using AddOption(). 461 462 Returns false of the option is not present or is not of the same type. 463 */ 464 bool SetOptionOctets( 465 const PString & name, ///< Option name 466 const BYTE * data, ///< Octets in option 467 PINDEX length ///< Number of octets 468 ); 469 470 /**Get a copy of the list of media formats that have been registered. 471 */ 472 static OpalMediaFormatList GetAllRegisteredMediaFormats(); 473 static void GetAllRegisteredMediaFormats( 474 OpalMediaFormatList & copy ///< List to receive the copy of the master list 475 ); 476 477 /**Set the options on the master format list entry. 478 The media format must already be registered. Returns false if not. 479 */ 480 static bool SetRegisteredMediaFormat( 481 const OpalMediaFormat & mediaFormat ///< Media format to copy to master list 482 ); 483 484 /**Remove the media format from master format list entry. 485 The media format must already be registered. Returns false if not. 486 */ 487 static bool RemoveRegisteredMediaFormat( 488 const OpalMediaFormat & mediaFormat ///< Media format to copy to master list 489 ); 490 491 /** 492 * Add a new option to this media format 493 */ 494 bool AddOption( 495 OpalMediaOption * option, 496 PBoolean overwrite = PFalse 497 ); 498 499 /** 500 * Determine if media format has the specified option. 501 */ 502 bool HasOption(const PString & name) const; 503 504 /** 505 * Get a pointer to the specified media format option. 506 * Returns NULL if thee option does not exist. 507 */ 508 OpalMediaOption * FindOption( 509 const PString & name 510 ) const; 511 512 /** Returns PTrue if the media format is valid for the protocol specified 513 This allow plugin codecs to customise which protocols they are valid for 514 The default implementation returns true unless the protocol is H.323 515 and the rtpEncodingName is NULL 516 */ 517 bool IsValidForProtocol(const PString & protocol) const; 518 519 time_t GetCodecVersionTime() const; 520 521 static const PString & MediaPacketizationOption(); 522 static const PString & MediaPacketizationsOption(); 523 524 SIP_PYOBJECT __repr__(); 525%MethodCode 526 sipRes = PyString_FromString(sipCpp->GetName()); 527%End 528 529 int __nonzero__(); 530%MethodCode 531 sipRes = sipCpp->IsValid(); 532%End 533 534 int __contains__(const PString & name); 535%MethodCode 536 sipRes = (*a0 == sipCpp->GetName()); 537%End 538 539 int __eq__(const PString & name); 540%MethodCode 541 sipRes = (*a0 == sipCpp->GetName()); 542%End 543 544}; 545 546class OpalMediaFormatInternal : PObject 547{ 548 public: 549 OpalMediaFormatInternal( 550 const char * fullName, 551 const OpalMediaType & mediaType, 552 RTP_DataFrame::PayloadTypes rtpPayloadType, 553 const char * encodingName, 554 PBoolean needsJitter, 555 unsigned bandwidth, 556 PINDEX frameSize, 557 unsigned frameTime, 558 unsigned clockRate, 559 time_t timeStamp 560 ); 561 562 const PCaselessString & GetName() const; 563 564 virtual PObject * Clone() const; 565 566 virtual bool IsValid() const; 567 virtual bool IsTransportable() const; 568 569 virtual PStringToString GetOptions() const; 570 virtual bool GetOptionValue(const PString & name, PString & value) const; 571 virtual bool SetOptionValue(const PString & name, const PString & value); 572 virtual bool GetOptionBoolean(const PString & name, bool dflt) const; 573 virtual bool SetOptionBoolean(const PString & name, bool value); 574 virtual int GetOptionInteger(const PString & name, int dflt) const; 575 virtual bool SetOptionInteger(const PString & name, int value); 576 virtual double GetOptionReal(const PString & name, double dflt) const; 577 virtual bool SetOptionReal(const PString & name, double value); 578 virtual PINDEX GetOptionEnum(const PString & name, PINDEX dflt) const; 579 virtual bool SetOptionEnum(const PString & name, PINDEX value); 580 virtual PString GetOptionString(const PString & name, const PString & dflt) const; 581 virtual bool SetOptionString(const PString & name, const PString & value); 582 virtual bool GetOptionOctets(const PString & name, PBYTEArray & octets) const; 583 virtual bool SetOptionOctets(const PString & name, const PBYTEArray & octets); 584 virtual bool SetOptionOctets(const PString & name, const BYTE * data, PINDEX length); 585 virtual bool AddOption(OpalMediaOption * option, PBoolean overwrite = false); 586 virtual OpalMediaOption * FindOption(const PString & name) const; 587 588 virtual bool ToNormalisedOptions(); 589 virtual bool ToCustomisedOptions(); 590 virtual bool Merge(const OpalMediaFormatInternal & mediaFormat); 591 592 virtual bool ValidateMerge(const OpalMediaFormatInternal & mediaFormat) const; 593 594 virtual bool IsValidForProtocol(const PString & protocol) const; 595}; 596 597class OpalAudioFormat : OpalMediaFormat 598{ 599 public: 600 OpalAudioFormat( 601 OpalMediaFormatInternal * info = NULL 602 ); 603 604 OpalAudioFormat( 605 const char * fullName, ///< Full name of media format 606 RTP_DataFrame::PayloadTypes rtpPayloadType, ///< RTP payload type code 607 const char * encodingName,///< RTP encoding name 608 PINDEX frameSize, ///< Size of frame in bytes (if applicable) 609 unsigned frameTime, ///< Time for frame in RTP units (if applicable) 610 unsigned rxFrames, ///< Maximum number of frames per packet we can receive 611 unsigned txFrames, ///< Desired number of frames per packet we transmit 612 unsigned maxFrames = 256, ///< Maximum possible frames per packet 613 unsigned clockRate = 8000, ///< Clock Rate 614 time_t timeStamp = 0 ///< timestamp (for versioning) 615 ); 616 617 static const PString & RxFramesPerPacketOption(); 618 static const PString & TxFramesPerPacketOption(); 619 static const PString & MaxFramesPerPacketOption(); 620 static const PString & ChannelsOption(); 621}; 622 623 624%MappedType OpalMediaFormatList 625{ 626%TypeHeaderCode 627#include <ptlib.h> 628#include <ptlib/lists.h> 629#include <opal/mediafmt.h> 630%End 631 632%ConvertFromTypeCode 633 // Create the list. 634 PyObject *l; 635 SIP_SSIZE_T i = 0; 636 637 if ((l = PyList_New(sipCpp->GetSize())) == NULL) 638 return NULL; 639 640 // Go through each element in the C++ instance and convert it to a 641 // wrapped TYPE. 642 for (OpalMediaFormatList::iterator iter = sipCpp->begin(); iter != sipCpp->end(); iter++) 643 { 644 OpalMediaFormat *fmt = new OpalMediaFormat(*iter); 645 PyObject *pobj; 646 647 // Get the Python wrapper for the Type instance, creating a new 648 // one if necessary, and handle any ownership transfer. 649 if ((pobj = sipConvertFromNewType(fmt, sipType_OpalMediaFormat, Py_None)) == NULL) 650 { 651 // There was an error so garbage collect the Python list. 652 Py_DECREF(l); 653 return NULL; 654 } 655 656 // Add the wrapper to the list. 657 PyList_SET_ITEM(l, i++, pobj); 658 } 659 660 // Return the Python list. 661 return l; 662%End 663 664%ConvertToTypeCode 665 // Check if type is compatible 666 if (sipIsErr == NULL) 667 { 668 // Must be any iterable 669 PyObject *i = PyObject_GetIter(sipPy); 670 bool iterable = (i != NULL); 671 Py_XDECREF(i); 672 return iterable; 673 } 674 675 // Iterate over the object 676 PyObject *iterator = PyObject_GetIter(sipPy); 677 PyObject *item; 678 int state; 679 680 OpalMediaFormatList *plist = new OpalMediaFormatList; 681 682 while ((item = PyIter_Next(iterator))) 683 { 684 if (!sipCanConvertToType(item, sipType_OpalMediaFormat, SIP_NOT_NONE)) 685 { 686 PyErr_Format(PyExc_TypeError, "object in iterable cannot be converted to OpalMediaFormat"); 687 *sipIsErr = 1; 688 break; 689 } 690 691 //Python should retain ownership, as we are creating a copy of this object in our list. 692 OpalMediaFormat* p = reinterpret_cast<OpalMediaFormat*>( 693 sipConvertToType(item, sipType_OpalMediaFormat, Py_None, SIP_NOT_NONE, &state, sipIsErr)); 694 695 if (!*sipIsErr) 696 *plist+=*p; 697 698 sipReleaseType(p, sipType_OpalMediaFormat, state); 699 Py_DECREF(item); 700 } 701 702 Py_DECREF(iterator); 703 704 if (*sipIsErr) 705 { 706 delete plist; 707 return 0; 708 } 709 710 *sipCppPtr = plist; 711 return sipGetState(sipTransferObj); 712%End 713}; 714 715 716class OpalVideoFormat : OpalMediaFormat 717{ 718%TypeHeaderCode 719#include <ptlib.h> 720#include <opal/mediafmt.h> 721%End 722 723 public: 724 OpalVideoFormat( 725 const char * fullName, ///< Full name of media format 726 RTP_DataFrame::PayloadTypes rtpPayloadType, ///< RTP payload type code 727 const char * encodingName,///< RTP encoding name 728 unsigned maxFrameWidth, ///< Width of video frame 729 unsigned maxFrameHeight, ///< Height of video frame 730 unsigned maxFrameRate, ///< Number of frames per second 731 unsigned maxBitRate, ///< Maximum bits per second 732 time_t timeStamp = 0 ///< timestamp (for versioning) 733 ); 734 735 static const PString & FrameWidthOption(); 736 static const PString & FrameHeightOption(); 737 static const PString & MinRxFrameWidthOption(); 738 static const PString & MinRxFrameHeightOption(); 739 static const PString & MaxRxFrameWidthOption(); 740 static const PString & MaxRxFrameHeightOption(); 741 static const PString & TemporalSpatialTradeOffOption(); 742 static const PString & TxKeyFramePeriodOption(); 743 static const PString & RateControlEnableOption(); 744 static const PString & RateControllerOption(); 745 746 /**The "role" of the content in the video stream based on this media 747 format. This is based on RFC4796 and H.239 semantics and is an 748 enumeration consisting of: 749 Value H.239 RFC4796 750 NoRole Not used (not populated) 751 Presentation Presentation (0x01) slides 752 Main Live (0x02) main 753 Speaker Live (0x02) speaker 754 SignLanguage Live (0x02) sl 755 */ 756 enum ContentRole { 757 eNoRole, 758 ePresentation, 759 eMainRole, 760 eSpeaker, 761 eSignLanguage, 762 eNumRoles 763 }; 764 765 enum 766 { 767 ContentRoleMask = 15 768 }; 769 770 static unsigned ContentRoleBit(ContentRole contentRole); 771 static const PString & ContentRoleOption(); 772 static const PString & ContentRoleMaskOption(); 773};