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