1 #ifndef MODULE_COMMON_TYPES_H 2 #define MODULE_COMMON_TYPES_H 3 4 #include <cstring> // memcpy 5 #include <assert.h> 6 7 #include "typedefs.h" 8 #include "common_types.h" 9 10 #ifdef _WIN32 11 #pragma warning(disable:4351) // remove warning "new behavior: elements of array 12 // 'array' will be default initialized" 13 #endif 14 15 namespace webrtc 16 { 17 struct RTPHeader 18 { 19 bool markerBit; 20 WebRtc_UWord8 payloadType; 21 WebRtc_UWord16 sequenceNumber; 22 WebRtc_UWord32 timestamp; 23 WebRtc_UWord32 ssrc; 24 WebRtc_UWord8 numCSRCs; 25 WebRtc_UWord32 arrOfCSRCs[kRtpCsrcSize]; 26 WebRtc_UWord8 paddingLength; 27 WebRtc_UWord16 headerLength; 28 }; 29 30 struct RTPHeaderExtension 31 { 32 WebRtc_Word32 transmissionTimeOffset; 33 }; 34 35 struct RTPAudioHeader 36 { 37 WebRtc_UWord8 numEnergy; // number of valid entries in arrOfEnergy 38 WebRtc_UWord8 arrOfEnergy[kRtpCsrcSize]; // one energy byte (0-9) per channel 39 bool isCNG; // is this CNG 40 WebRtc_UWord8 channel; // number of channels 2 = stereo 41 }; 42 43 struct RTPVideoHeaderH263 44 { 45 void InitRTPVideoHeaderH263() {}; 46 bool independentlyDecodable; // H.263-1998 if no P bit it's not independently decodable 47 bool bits; // H.263 mode B, Xor the lasy byte of previus packet with the 48 // first byte of this packet 49 }; 50 51 enum {kNoPictureId = -1}; 52 enum {kNoTl0PicIdx = -1}; 53 enum {kNoTemporalIdx = -1}; 54 enum {kNoKeyIdx = -1}; 55 enum {kNoSimulcastIdx = 0}; 56 57 struct RTPVideoHeaderVP8 58 { 59 void InitRTPVideoHeaderVP8() 60 { 61 nonReference = false; 62 pictureId = kNoPictureId; 63 tl0PicIdx = kNoTl0PicIdx; 64 temporalIdx = kNoTemporalIdx; 65 layerSync = false; 66 keyIdx = kNoKeyIdx; 67 partitionId = 0; 68 beginningOfPartition = false; 69 frameWidth = 0; 70 frameHeight = 0; 71 } 72 73 bool nonReference; // Frame is discardable. 74 WebRtc_Word16 pictureId; // Picture ID index, 15 bits; 75 // kNoPictureId if PictureID does not exist. 76 WebRtc_Word16 tl0PicIdx; // TL0PIC_IDX, 8 bits; 77 // kNoTl0PicIdx means no value provided. 78 WebRtc_Word8 temporalIdx; // Temporal layer index, or kNoTemporalIdx. 79 bool layerSync; // This frame is a layer sync frame. 80 // Disabled if temporalIdx == kNoTemporalIdx. 81 int keyIdx; // 5 bits; kNoKeyIdx means not used. 82 int partitionId; // VP8 partition ID 83 bool beginningOfPartition; // True if this packet is the first 84 // in a VP8 partition. Otherwise false 85 int frameWidth; // Exists for key frames. 86 int frameHeight; // Exists for key frames. 87 }; 88 union RTPVideoTypeHeader 89 { 90 RTPVideoHeaderH263 H263; 91 RTPVideoHeaderVP8 VP8; 92 }; 93 94 enum RTPVideoCodecTypes 95 { 96 kRTPVideoGeneric = 0, 97 kRTPVideoH263 = 1, 98 kRTPVideoMPEG4 = 5, 99 kRTPVideoVP8 = 8, 100 kRTPVideoNoVideo = 10, 101 kRTPVideoFEC = 11, 102 kRTPVideoI420 = 12 103 }; 104 struct RTPVideoHeader 105 { 106 WebRtc_UWord16 width; // size 107 WebRtc_UWord16 height; 108 109 bool isFirstPacket; // first packet in frame 110 WebRtc_UWord8 simulcastIdx; // Index if the simulcast encoder creating 111 // this frame, 0 if not using simulcast. 112 RTPVideoCodecTypes codec; 113 RTPVideoTypeHeader codecHeader; 114 }; 115 union RTPTypeHeader 116 { 117 RTPAudioHeader Audio; 118 RTPVideoHeader Video; 119 }; 120 121 struct WebRtcRTPHeader 122 { 123 RTPHeader header; 124 FrameType frameType; 125 RTPTypeHeader type; 126 RTPHeaderExtension extension; 127 }; 128 129 class RTPFragmentationHeader 130 { 131 public: 132 RTPFragmentationHeader() : 133 fragmentationVectorSize(0), 134 fragmentationOffset(NULL), 135 fragmentationLength(NULL), 136 fragmentationTimeDiff(NULL), 137 fragmentationPlType(NULL) 138 {}; 139 140 ~RTPFragmentationHeader() 141 { 142 delete [] fragmentationOffset; 143 delete [] fragmentationLength; 144 delete [] fragmentationTimeDiff; 145 delete [] fragmentationPlType; 146 } 147 148 RTPFragmentationHeader& operator=(const RTPFragmentationHeader& header) 149 { 150 if(this == &header) 151 { 152 return *this; 153 } 154 155 if(header.fragmentationVectorSize != fragmentationVectorSize) 156 { 157 // new size of vectors 158 159 // delete old 160 delete [] fragmentationOffset; 161 fragmentationOffset = NULL; 162 delete [] fragmentationLength; 163 fragmentationLength = NULL; 164 delete [] fragmentationTimeDiff; 165 fragmentationTimeDiff = NULL; 166 delete [] fragmentationPlType; 167 fragmentationPlType = NULL; 168 169 if(header.fragmentationVectorSize > 0) 170 { 171 // allocate new 172 if(header.fragmentationOffset) 173 { 174 fragmentationOffset = new WebRtc_UWord32[header.fragmentationVectorSize]; 175 } 176 if(header.fragmentationLength) 177 { 178 fragmentationLength = new WebRtc_UWord32[header.fragmentationVectorSize]; 179 } 180 if(header.fragmentationTimeDiff) 181 { 182 fragmentationTimeDiff = new WebRtc_UWord16[header.fragmentationVectorSize]; 183 } 184 if(header.fragmentationPlType) 185 { 186 fragmentationPlType = new WebRtc_UWord8[header.fragmentationVectorSize]; 187 } 188 } 189 // set new size 190 fragmentationVectorSize = header.fragmentationVectorSize; 191 } 192 193 if(header.fragmentationVectorSize > 0) 194 { 195 // copy values 196 if(header.fragmentationOffset) 197 { 198 memcpy(fragmentationOffset, header.fragmentationOffset, 199 header.fragmentationVectorSize * sizeof(WebRtc_UWord32)); 200 } 201 if(header.fragmentationLength) 202 { 203 memcpy(fragmentationLength, header.fragmentationLength, 204 header.fragmentationVectorSize * sizeof(WebRtc_UWord32)); 205 } 206 if(header.fragmentationTimeDiff) 207 { 208 memcpy(fragmentationTimeDiff, header.fragmentationTimeDiff, 209 header.fragmentationVectorSize * sizeof(WebRtc_UWord16)); 210 } 211 if(header.fragmentationPlType) 212 { 213 memcpy(fragmentationPlType, header.fragmentationPlType, 214 header.fragmentationVectorSize * sizeof(WebRtc_UWord8)); 215 } 216 } 217 return *this; 218 } 219 void VerifyAndAllocateFragmentationHeader( const WebRtc_UWord16 size) 220 { 221 if( fragmentationVectorSize < size) 222 { 223 WebRtc_UWord16 oldVectorSize = fragmentationVectorSize; 224 { 225 // offset 226 WebRtc_UWord32* oldOffsets = fragmentationOffset; 227 fragmentationOffset = new WebRtc_UWord32[size]; 228 memset(fragmentationOffset+oldVectorSize, 0, 229 sizeof(WebRtc_UWord32)*(size-oldVectorSize)); 230 // copy old values 231 memcpy(fragmentationOffset,oldOffsets, sizeof(WebRtc_UWord32) * oldVectorSize); 232 delete[] oldOffsets; 233 } 234 // length 235 { 236 WebRtc_UWord32* oldLengths = fragmentationLength; 237 fragmentationLength = new WebRtc_UWord32[size]; 238 memset(fragmentationLength+oldVectorSize, 0, 239 sizeof(WebRtc_UWord32) * (size- oldVectorSize)); 240 memcpy(fragmentationLength, oldLengths, 241 sizeof(WebRtc_UWord32) * oldVectorSize); 242 delete[] oldLengths; 243 } 244 // time diff 245 { 246 WebRtc_UWord16* oldTimeDiffs = fragmentationTimeDiff; 247 fragmentationTimeDiff = new WebRtc_UWord16[size]; 248 memset(fragmentationTimeDiff+oldVectorSize, 0, 249 sizeof(WebRtc_UWord16) * (size- oldVectorSize)); 250 memcpy(fragmentationTimeDiff, oldTimeDiffs, 251 sizeof(WebRtc_UWord16) * oldVectorSize); 252 delete[] oldTimeDiffs; 253 } 254 // payload type 255 { 256 WebRtc_UWord8* oldTimePlTypes = fragmentationPlType; 257 fragmentationPlType = new WebRtc_UWord8[size]; 258 memset(fragmentationPlType+oldVectorSize, 0, 259 sizeof(WebRtc_UWord8) * (size- oldVectorSize)); 260 memcpy(fragmentationPlType, oldTimePlTypes, 261 sizeof(WebRtc_UWord8) * oldVectorSize); 262 delete[] oldTimePlTypes; 263 } 264 fragmentationVectorSize = size; 265 } 266 } 267 268 WebRtc_UWord16 fragmentationVectorSize; // Number of fragmentations 269 WebRtc_UWord32* fragmentationOffset; // Offset of pointer to data for each fragm. 270 WebRtc_UWord32* fragmentationLength; // Data size for each fragmentation 271 WebRtc_UWord16* fragmentationTimeDiff; // Timestamp difference relative "now" for 272 // each fragmentation 273 WebRtc_UWord8* fragmentationPlType; // Payload type of each fragmentation 274 }; 275 276 struct RTCPVoIPMetric 277 { 278 // RFC 3611 4.7 279 WebRtc_UWord8 lossRate; 280 WebRtc_UWord8 discardRate; 281 WebRtc_UWord8 burstDensity; 282 WebRtc_UWord8 gapDensity; 283 WebRtc_UWord16 burstDuration; 284 WebRtc_UWord16 gapDuration; 285 WebRtc_UWord16 roundTripDelay; 286 WebRtc_UWord16 endSystemDelay; 287 WebRtc_UWord8 signalLevel; 288 WebRtc_UWord8 noiseLevel; 289 WebRtc_UWord8 RERL; 290 WebRtc_UWord8 Gmin; 291 WebRtc_UWord8 Rfactor; 292 WebRtc_UWord8 extRfactor; 293 WebRtc_UWord8 MOSLQ; 294 WebRtc_UWord8 MOSCQ; 295 WebRtc_UWord8 RXconfig; 296 WebRtc_UWord16 JBnominal; 297 WebRtc_UWord16 JBmax; 298 WebRtc_UWord16 JBabsMax; 299 }; 300 301 // class describing a complete, or parts of an encoded frame. 302 class EncodedVideoData 303 { 304 public: 305 EncodedVideoData() : 306 completeFrame(false), 307 missingFrame(false), 308 payloadData(NULL), 309 payloadSize(0), 310 bufferSize(0) 311 {}; 312 313 EncodedVideoData(const EncodedVideoData& data) 314 { 315 payloadType = data.payloadType; 316 timeStamp = data.timeStamp; 317 renderTimeMs = data.renderTimeMs; 318 encodedWidth = data.encodedWidth; 319 encodedHeight = data.encodedHeight; 320 completeFrame = data.completeFrame; 321 missingFrame = data.missingFrame; 322 payloadSize = data.payloadSize; 323 fragmentationHeader = data.fragmentationHeader; 324 frameType = data.frameType; 325 codec = data.codec; 326 if (data.payloadSize > 0) 327 { 328 payloadData = new WebRtc_UWord8[data.payloadSize]; 329 memcpy(payloadData, data.payloadData, data.payloadSize); 330 } 331 else 332 { 333 payloadData = NULL; 334 } 335 } 336 337 338 ~EncodedVideoData() 339 { 340 delete [] payloadData; 341 }; 342 343 EncodedVideoData& operator=(const EncodedVideoData& data) 344 { 345 if (this == &data) 346 { 347 return *this; 348 } 349 payloadType = data.payloadType; 350 timeStamp = data.timeStamp; 351 renderTimeMs = data.renderTimeMs; 352 encodedWidth = data.encodedWidth; 353 encodedHeight = data.encodedHeight; 354 completeFrame = data.completeFrame; 355 missingFrame = data.missingFrame; 356 payloadSize = data.payloadSize; 357 fragmentationHeader = data.fragmentationHeader; 358 frameType = data.frameType; 359 codec = data.codec; 360 if (data.payloadSize > 0) 361 { 362 delete [] payloadData; 363 payloadData = new WebRtc_UWord8[data.payloadSize]; 364 memcpy(payloadData, data.payloadData, data.payloadSize); 365 bufferSize = data.payloadSize; 366 } 367 return *this; 368 }; 369 void VerifyAndAllocate( const WebRtc_UWord32 size) 370 { 371 if (bufferSize < size) 372 { 373 WebRtc_UWord8* oldPayload = payloadData; 374 payloadData = new WebRtc_UWord8[size]; 375 memcpy(payloadData, oldPayload, sizeof(WebRtc_UWord8) * payloadSize); 376 377 bufferSize = size; 378 delete[] oldPayload; 379 } 380 } 381 382 WebRtc_UWord8 payloadType; 383 WebRtc_UWord32 timeStamp; 384 WebRtc_Word64 renderTimeMs; 385 WebRtc_UWord32 encodedWidth; 386 WebRtc_UWord32 encodedHeight; 387 bool completeFrame; 388 bool missingFrame; 389 WebRtc_UWord8* payloadData; 390 WebRtc_UWord32 payloadSize; 391 WebRtc_UWord32 bufferSize; 392 RTPFragmentationHeader fragmentationHeader; 393 FrameType frameType; 394 VideoCodecType codec; 395 }; 396 397 // Video Content Metrics 398 struct VideoContentMetrics 399 { 400 VideoContentMetrics(): motionMagnitudeNZ(0), sizeZeroMotion(0), spatialPredErr(0), 401 spatialPredErrH(0), spatialPredErrV(0), motionPredErr(0), 402 motionHorizontalness(0), motionClusterDistortion(0), 403 nativeWidth(0), nativeHeight(0), contentChange(false) { } 404 void Reset(){ motionMagnitudeNZ = 0; sizeZeroMotion = 0; spatialPredErr = 0; 405 spatialPredErrH = 0; spatialPredErrV = 0; motionPredErr = 0; 406 motionHorizontalness = 0; motionClusterDistortion = 0; 407 nativeWidth = 0; nativeHeight = 0; contentChange = false; } 408 409 float motionMagnitudeNZ; 410 float sizeZeroMotion; 411 float spatialPredErr; 412 float spatialPredErrH; 413 float spatialPredErrV; 414 float motionPredErr; 415 float motionHorizontalness; 416 float motionClusterDistortion; 417 WebRtc_UWord32 nativeWidth; 418 WebRtc_UWord32 nativeHeight; 419 WebRtc_UWord32 nativeFrameRate; 420 bool contentChange; 421 }; 422 423 /************************************************* 424 * 425 * VideoFrame class 426 * 427 * The VideoFrame class allows storing and 428 * handling of video frames. 429 * 430 * 431 *************************************************/ 432 class VideoFrame 433 { 434 public: 435 VideoFrame(); 436 ~VideoFrame(); 437 /** 438 * Verifies that current allocated buffer size is larger than or equal to the input size. 439 * If the current buffer size is smaller, a new allocation is made and the old buffer data 440 * is copied to the new buffer. 441 * Buffer size is updated to minimumSize. 442 */ 443 WebRtc_Word32 VerifyAndAllocate(const WebRtc_UWord32 minimumSize); 444 /** 445 * Update length of data buffer in frame. Function verifies that new length is less or 446 * equal to allocated size. 447 */ 448 WebRtc_Word32 SetLength(const WebRtc_UWord32 newLength); 449 /* 450 * Swap buffer and size data 451 */ 452 WebRtc_Word32 Swap(WebRtc_UWord8*& newMemory, 453 WebRtc_UWord32& newLength, 454 WebRtc_UWord32& newSize); 455 /* 456 * Swap buffer and size data 457 */ 458 WebRtc_Word32 SwapFrame(VideoFrame& videoFrame); 459 /** 460 * Copy buffer: If newLength is bigger than allocated size, a new buffer of size length 461 * is allocated. 462 */ 463 WebRtc_Word32 CopyFrame(const VideoFrame& videoFrame); 464 /** 465 * Copy buffer: If newLength is bigger than allocated size, a new buffer of size length 466 * is allocated. 467 */ 468 WebRtc_Word32 CopyFrame(WebRtc_UWord32 length, const WebRtc_UWord8* sourceBuffer); 469 /** 470 * Delete VideoFrame and resets members to zero 471 */ 472 void Free(); 473 /** 474 * Set frame timestamp (90kHz) 475 */ 476 void SetTimeStamp(const WebRtc_UWord32 timeStamp) {_timeStamp = timeStamp;} 477 /** 478 * Get pointer to frame buffer 479 */ 480 WebRtc_UWord8* Buffer() const {return _buffer;} 481 482 WebRtc_UWord8*& Buffer() {return _buffer;} 483 484 /** 485 * Get allocated buffer size 486 */ 487 WebRtc_UWord32 Size() const {return _bufferSize;} 488 /** 489 * Get frame length 490 */ 491 WebRtc_UWord32 Length() const {return _bufferLength;} 492 /** 493 * Get frame timestamp (90kHz) 494 */ 495 WebRtc_UWord32 TimeStamp() const {return _timeStamp;} 496 /** 497 * Get frame width 498 */ 499 WebRtc_UWord32 Width() const {return _width;} 500 /** 501 * Get frame height 502 */ 503 WebRtc_UWord32 Height() const {return _height;} 504 /** 505 * Set frame width 506 */ 507 void SetWidth(const WebRtc_UWord32 width) {_width = width;} 508 /** 509 * Set frame height 510 */ 511 void SetHeight(const WebRtc_UWord32 height) {_height = height;} 512 /** 513 * Set render time in miliseconds 514 */ 515 void SetRenderTime(const WebRtc_Word64 renderTimeMs) {_renderTimeMs = renderTimeMs;} 516 /** 517 * Get render time in miliseconds 518 */ 519 WebRtc_Word64 RenderTimeMs() const {return _renderTimeMs;} 520 521 private: 522 void Set(WebRtc_UWord8* buffer, 523 WebRtc_UWord32 size, 524 WebRtc_UWord32 length, 525 WebRtc_UWord32 timeStamp); 526 527 WebRtc_UWord8* _buffer; // Pointer to frame buffer 528 WebRtc_UWord32 _bufferSize; // Allocated buffer size 529 WebRtc_UWord32 _bufferLength; // Length (in bytes) of buffer 530 WebRtc_UWord32 _timeStamp; // Timestamp of frame (90kHz) 531 WebRtc_UWord32 _width; 532 WebRtc_UWord32 _height; 533 WebRtc_Word64 _renderTimeMs; 534 }; // end of VideoFrame class declaration 535 536 // inline implementation of VideoFrame class: 537 inline 538 VideoFrame::VideoFrame(): 539 _buffer(0), 540 _bufferSize(0), 541 _bufferLength(0), 542 _timeStamp(0), 543 _width(0), 544 _height(0), 545 _renderTimeMs(0) 546 { 547 // 548 } 549 inline 550 VideoFrame::~VideoFrame() 551 { 552 if(_buffer) 553 { 554 delete [] _buffer; 555 _buffer = NULL; 556 } 557 } 558 559 560 inline 561 WebRtc_Word32 562 VideoFrame::VerifyAndAllocate(const WebRtc_UWord32 minimumSize) 563 { 564 if (minimumSize < 1) 565 { 566 return -1; 567 } 568 if(minimumSize > _bufferSize) 569 { 570 // create buffer of sufficient size 571 WebRtc_UWord8* newBufferBuffer = new WebRtc_UWord8[minimumSize]; 572 if(_buffer) 573 { 574 // copy old data 575 memcpy(newBufferBuffer, _buffer, _bufferSize); 576 delete [] _buffer; 577 } 578 _buffer = newBufferBuffer; 579 _bufferSize = minimumSize; 580 } 581 return 0; 582 } 583 584 inline 585 WebRtc_Word32 586 VideoFrame::SetLength(const WebRtc_UWord32 newLength) 587 { 588 if (newLength >_bufferSize ) 589 { // can't accomodate new value 590 return -1; 591 } 592 _bufferLength = newLength; 593 return 0; 594 } 595 596 inline 597 WebRtc_Word32 598 VideoFrame::SwapFrame(VideoFrame& videoFrame) 599 { 600 WebRtc_UWord32 tmpTimeStamp = _timeStamp; 601 WebRtc_UWord32 tmpWidth = _width; 602 WebRtc_UWord32 tmpHeight = _height; 603 WebRtc_Word64 tmpRenderTime = _renderTimeMs; 604 605 _timeStamp = videoFrame._timeStamp; 606 _width = videoFrame._width; 607 _height = videoFrame._height; 608 _renderTimeMs = videoFrame._renderTimeMs; 609 610 videoFrame._timeStamp = tmpTimeStamp; 611 videoFrame._width = tmpWidth; 612 videoFrame._height = tmpHeight; 613 videoFrame._renderTimeMs = tmpRenderTime; 614 615 return Swap(videoFrame._buffer, videoFrame._bufferLength, videoFrame._bufferSize); 616 } 617 618 inline 619 WebRtc_Word32 620 VideoFrame::Swap(WebRtc_UWord8*& newMemory, WebRtc_UWord32& newLength, WebRtc_UWord32& newSize) 621 { 622 WebRtc_UWord8* tmpBuffer = _buffer; 623 WebRtc_UWord32 tmpLength = _bufferLength; 624 WebRtc_UWord32 tmpSize = _bufferSize; 625 _buffer = newMemory; 626 _bufferLength = newLength; 627 _bufferSize = newSize; 628 newMemory = tmpBuffer; 629 newLength = tmpLength; 630 newSize = tmpSize; 631 return 0; 632 } 633 634 inline 635 WebRtc_Word32 636 VideoFrame::CopyFrame(WebRtc_UWord32 length, const WebRtc_UWord8* sourceBuffer) 637 { 638 if (length > _bufferSize) 639 { 640 WebRtc_Word32 ret = VerifyAndAllocate(length); 641 if (ret < 0) 642 { 643 return ret; 644 } 645 } 646 memcpy(_buffer, sourceBuffer, length); 647 _bufferLength = length; 648 return 0; 649 } 650 651 inline 652 WebRtc_Word32 653 VideoFrame::CopyFrame(const VideoFrame& videoFrame) 654 { 655 if(CopyFrame(videoFrame.Length(), videoFrame.Buffer()) != 0) 656 { 657 return -1; 658 } 659 _timeStamp = videoFrame._timeStamp; 660 _width = videoFrame._width; 661 _height = videoFrame._height; 662 _renderTimeMs = videoFrame._renderTimeMs; 663 return 0; 664 } 665 666 inline 667 void 668 VideoFrame::Free() 669 { 670 _timeStamp = 0; 671 _bufferLength = 0; 672 _bufferSize = 0; 673 _height = 0; 674 _width = 0; 675 _renderTimeMs = 0; 676 677 if(_buffer) 678 { 679 delete [] _buffer; 680 _buffer = NULL; 681 } 682 } 683 684 685 /************************************************* 686 * 687 * AudioFrame class 688 * 689 * The AudioFrame class holds up to 60 ms wideband 690 * audio. It allows for adding and subtracting frames 691 * while keeping track of the resulting states. 692 * 693 * Note 694 * - The +operator assume that you would never add 695 * exact opposite frames when deciding the resulting 696 * state. To do this use the -operator. 697 * 698 * - _audioChannel of 1 indicated mono, and 2 699 * indicates stereo. 700 * 701 * - _payloadDataLengthInSamples is the number of 702 * samples per channel. Therefore, the total 703 * number of samples in _payloadData is 704 * (_payloadDataLengthInSamples * _audioChannel). 705 * 706 * - Stereo data is stored in interleaved fashion 707 * starting with the left channel. 708 * 709 *************************************************/ 710 class AudioFrame 711 { 712 public: 713 enum{kMaxAudioFrameSizeSamples = 3840}; // stereo 32KHz 60ms 2*32*60 714 715 enum VADActivity 716 { 717 kVadActive = 0, 718 kVadPassive = 1, 719 kVadUnknown = 2 720 }; 721 enum SpeechType 722 { 723 kNormalSpeech = 0, 724 kPLC = 1, 725 kCNG = 2, 726 kPLCCNG = 3, 727 kUndefined = 4 728 }; 729 730 AudioFrame(); 731 virtual ~AudioFrame(); 732 733 WebRtc_Word32 UpdateFrame( 734 const WebRtc_Word32 id, 735 const WebRtc_UWord32 timeStamp, 736 const WebRtc_Word16* payloadData, 737 const WebRtc_UWord16 payloadDataLengthInSamples, 738 const int frequencyInHz, 739 const SpeechType speechType, 740 const VADActivity vadActivity, 741 const WebRtc_UWord8 audioChannel = 1, 742 const WebRtc_Word32 volume = -1, 743 const WebRtc_Word32 energy = -1); 744 745 AudioFrame& Append(const AudioFrame& rhs); 746 747 void Mute() const; 748 749 AudioFrame& operator=(const AudioFrame& rhs); 750 AudioFrame& operator>>=(const WebRtc_Word32 rhs); 751 AudioFrame& operator+=(const AudioFrame& rhs); 752 AudioFrame& operator-=(const AudioFrame& rhs); 753 754 WebRtc_Word32 _id; 755 WebRtc_UWord32 _timeStamp; 756 757 // Supporting Stereo, stereo samples are interleaved 758 mutable WebRtc_Word16 _payloadData[kMaxAudioFrameSizeSamples]; 759 WebRtc_UWord16 _payloadDataLengthInSamples; 760 int _frequencyInHz; 761 WebRtc_UWord8 _audioChannel; 762 SpeechType _speechType; 763 VADActivity _vadActivity; 764 765 WebRtc_UWord32 _energy; 766 WebRtc_Word32 _volume; 767 }; 768 769 inline 770 AudioFrame::AudioFrame() 771 : 772 _id(-1), 773 _timeStamp(0), 774 _payloadData(), 775 _payloadDataLengthInSamples(0), 776 _frequencyInHz(0), 777 _audioChannel(1), 778 _speechType(kUndefined), 779 _vadActivity(kVadUnknown), 780 _energy(0xffffffff), 781 _volume(0xffffffff) 782 { 783 } 784 785 inline 786 AudioFrame::~AudioFrame() 787 { 788 } 789 790 inline 791 WebRtc_Word32 792 AudioFrame::UpdateFrame( 793 const WebRtc_Word32 id, 794 const WebRtc_UWord32 timeStamp, 795 const WebRtc_Word16* payloadData, 796 const WebRtc_UWord16 payloadDataLengthInSamples, 797 const int frequencyInHz, 798 const SpeechType speechType, 799 const VADActivity vadActivity, 800 const WebRtc_UWord8 audioChannel, 801 const WebRtc_Word32 volume, 802 const WebRtc_Word32 energy) 803 { 804 _id = id; 805 _timeStamp = timeStamp; 806 _frequencyInHz = frequencyInHz; 807 _speechType = speechType; 808 _vadActivity = vadActivity; 809 _volume = volume; 810 _audioChannel = audioChannel; 811 _energy = energy; 812 813 if((payloadDataLengthInSamples > kMaxAudioFrameSizeSamples) || 814 (audioChannel > 2) || (audioChannel < 1)) 815 { 816 _payloadDataLengthInSamples = 0; 817 return -1; 818 } 819 _payloadDataLengthInSamples = payloadDataLengthInSamples; 820 if(payloadData != NULL) 821 { 822 memcpy(_payloadData, payloadData, sizeof(WebRtc_Word16) * 823 payloadDataLengthInSamples * _audioChannel); 824 } 825 else 826 { 827 memset(_payloadData,0,sizeof(WebRtc_Word16) * 828 payloadDataLengthInSamples * _audioChannel); 829 } 830 return 0; 831 } 832 833 inline 834 void 835 AudioFrame::Mute() const 836 { 837 memset(_payloadData, 0, _payloadDataLengthInSamples * sizeof(WebRtc_Word16)); 838 } 839 840 inline 841 AudioFrame& 842 AudioFrame::operator=(const AudioFrame& rhs) 843 { 844 // Sanity Check 845 if((rhs._payloadDataLengthInSamples > kMaxAudioFrameSizeSamples) || 846 (rhs._audioChannel > 2) || 847 (rhs._audioChannel < 1)) 848 { 849 return *this; 850 } 851 if(this == &rhs) 852 { 853 return *this; 854 } 855 _id = rhs._id; 856 _timeStamp = rhs._timeStamp; 857 _frequencyInHz = rhs._frequencyInHz; 858 _speechType = rhs._speechType; 859 _vadActivity = rhs._vadActivity; 860 _volume = rhs._volume; 861 _audioChannel = rhs._audioChannel; 862 _energy = rhs._energy; 863 864 _payloadDataLengthInSamples = rhs._payloadDataLengthInSamples; 865 memcpy(_payloadData, rhs._payloadData, 866 sizeof(WebRtc_Word16) * rhs._payloadDataLengthInSamples * _audioChannel); 867 868 return *this; 869 } 870 871 inline 872 AudioFrame& 873 AudioFrame::operator>>=(const WebRtc_Word32 rhs) 874 { 875 assert((_audioChannel > 0) && (_audioChannel < 3)); 876 if((_audioChannel > 2) || 877 (_audioChannel < 1)) 878 { 879 return *this; 880 } 881 for(WebRtc_UWord16 i = 0; i < _payloadDataLengthInSamples * _audioChannel; i++) 882 { 883 _payloadData[i] = WebRtc_Word16(_payloadData[i] >> rhs); 884 } 885 return *this; 886 } 887 888 inline 889 AudioFrame& 890 AudioFrame::Append(const AudioFrame& rhs) 891 { 892 // Sanity check 893 assert((_audioChannel > 0) && (_audioChannel < 3)); 894 if((_audioChannel > 2) || 895 (_audioChannel < 1)) 896 { 897 return *this; 898 } 899 if(_audioChannel != rhs._audioChannel) 900 { 901 return *this; 902 } 903 if((_vadActivity == kVadActive) || 904 rhs._vadActivity == kVadActive) 905 { 906 _vadActivity = kVadActive; 907 } 908 else if((_vadActivity == kVadUnknown) || 909 rhs._vadActivity == kVadUnknown) 910 { 911 _vadActivity = kVadUnknown; 912 } 913 if(_speechType != rhs._speechType) 914 { 915 _speechType = kUndefined; 916 } 917 918 WebRtc_UWord16 offset = _payloadDataLengthInSamples * _audioChannel; 919 for(WebRtc_UWord16 i = 0; 920 i < rhs._payloadDataLengthInSamples * rhs._audioChannel; 921 i++) 922 { 923 _payloadData[offset+i] = rhs._payloadData[i]; 924 } 925 _payloadDataLengthInSamples += rhs._payloadDataLengthInSamples; 926 return *this; 927 } 928 929 // merge vectors 930 inline 931 AudioFrame& 932 AudioFrame::operator+=(const AudioFrame& rhs) 933 { 934 // Sanity check 935 assert((_audioChannel > 0) && (_audioChannel < 3)); 936 if((_audioChannel > 2) || 937 (_audioChannel < 1)) 938 { 939 return *this; 940 } 941 if(_audioChannel != rhs._audioChannel) 942 { 943 return *this; 944 } 945 bool noPrevData = false; 946 if(_payloadDataLengthInSamples != rhs._payloadDataLengthInSamples) 947 { 948 if(_payloadDataLengthInSamples == 0) 949 { 950 // special case we have no data to start with 951 _payloadDataLengthInSamples = rhs._payloadDataLengthInSamples; 952 noPrevData = true; 953 } else 954 { 955 return *this; 956 } 957 } 958 959 if((_vadActivity == kVadActive) || 960 rhs._vadActivity == kVadActive) 961 { 962 _vadActivity = kVadActive; 963 } 964 else if((_vadActivity == kVadUnknown) || 965 rhs._vadActivity == kVadUnknown) 966 { 967 _vadActivity = kVadUnknown; 968 } 969 970 if(_speechType != rhs._speechType) 971 { 972 _speechType = kUndefined; 973 } 974 975 if(noPrevData) 976 { 977 memcpy(_payloadData, rhs._payloadData, 978 sizeof(WebRtc_Word16) * rhs._payloadDataLengthInSamples * _audioChannel); 979 } else 980 { 981 // IMPROVEMENT this can be done very fast in assembly 982 for(WebRtc_UWord16 i = 0; i < _payloadDataLengthInSamples * _audioChannel; i++) 983 { 984 WebRtc_Word32 wrapGuard = (WebRtc_Word32)_payloadData[i] + 985 (WebRtc_Word32)rhs._payloadData[i]; 986 if(wrapGuard < -32768) 987 { 988 _payloadData[i] = -32768; 989 }else if(wrapGuard > 32767) 990 { 991 _payloadData[i] = 32767; 992 }else 993 { 994 _payloadData[i] = (WebRtc_Word16)wrapGuard; 995 } 996 } 997 } 998 _energy = 0xffffffff; 999 _volume = 0xffffffff; 1000 return *this; 1001 } 1002 1003 inline 1004 AudioFrame& 1005 AudioFrame::operator-=(const AudioFrame& rhs) 1006 { 1007 // Sanity check 1008 assert((_audioChannel > 0) && (_audioChannel < 3)); 1009 if((_audioChannel > 2)|| 1010 (_audioChannel < 1)) 1011 { 1012 return *this; 1013 } 1014 if((_payloadDataLengthInSamples != rhs._payloadDataLengthInSamples) || 1015 (_audioChannel != rhs._audioChannel)) 1016 { 1017 return *this; 1018 } 1019 if((_vadActivity != kVadPassive) || 1020 rhs._vadActivity != kVadPassive) 1021 { 1022 _vadActivity = kVadUnknown; 1023 } 1024 _speechType = kUndefined; 1025 1026 for(WebRtc_UWord16 i = 0; i < _payloadDataLengthInSamples * _audioChannel; i++) 1027 { 1028 WebRtc_Word32 wrapGuard = (WebRtc_Word32)_payloadData[i] - 1029 (WebRtc_Word32)rhs._payloadData[i]; 1030 if(wrapGuard < -32768) 1031 { 1032 _payloadData[i] = -32768; 1033 } 1034 else if(wrapGuard > 32767) 1035 { 1036 _payloadData[i] = 32767; 1037 } 1038 else 1039 { 1040 _payloadData[i] = (WebRtc_Word16)wrapGuard; 1041 } 1042 } 1043 _energy = 0xffffffff; 1044 _volume = 0xffffffff; 1045 return *this; 1046 } 1047 1048 } // namespace webrtc 1049 1050 #endif // MODULE_COMMON_TYPES_H 1051