module_common_types.h revision c55a96383497a772a307b346368133960b02ad03
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
15namespace webrtc
16{
17struct 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
30struct RTPHeaderExtension
31{
32    WebRtc_Word32  transmissionTimeOffset;
33};
34
35struct 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
43struct 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
51enum {kNoPictureId = -1};
52enum {kNoTl0PicIdx = -1};
53enum {kNoTemporalIdx = -1};
54enum {kNoKeyIdx = -1};
55enum {kNoSimulcastIdx = 0};
56
57struct 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};
88union RTPVideoTypeHeader
89{
90    RTPVideoHeaderH263      H263;
91    RTPVideoHeaderVP8       VP8;
92};
93
94enum RTPVideoCodecTypes
95{
96    kRTPVideoGeneric  = 0,
97    kRTPVideoH263     = 1,
98    kRTPVideoMPEG4    = 5,
99    kRTPVideoVP8      = 8,
100    kRTPVideoNoVideo  = 10,
101    kRTPVideoFEC      = 11,
102    kRTPVideoI420     = 12
103};
104struct 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};
115union RTPTypeHeader
116{
117    RTPAudioHeader  Audio;
118    RTPVideoHeader  Video;
119};
120
121struct WebRtcRTPHeader
122{
123    RTPHeader       header;
124    FrameType       frameType;
125    RTPTypeHeader   type;
126    RTPHeaderExtension extension;
127};
128
129class RTPFragmentationHeader
130{
131public:
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
276struct 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.
302class EncodedVideoData
303{
304public:
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
398struct 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 *************************************************/
432class VideoFrame
433{
434public:
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
521private:
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:
537inline
538VideoFrame::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}
549inline
550VideoFrame::~VideoFrame()
551{
552    if(_buffer)
553    {
554        delete [] _buffer;
555        _buffer = NULL;
556    }
557}
558
559
560inline
561WebRtc_Word32
562VideoFrame::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
584inline
585WebRtc_Word32
586VideoFrame::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
596inline
597WebRtc_Word32
598VideoFrame::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
618inline
619WebRtc_Word32
620VideoFrame::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
634inline
635WebRtc_Word32
636VideoFrame::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
651inline
652WebRtc_Word32
653VideoFrame::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
666inline
667void
668VideoFrame::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 *************************************************/
710class AudioFrame
711{
712public:
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
769inline
770AudioFrame::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
785inline
786AudioFrame::~AudioFrame()
787{
788}
789
790inline
791WebRtc_Word32
792AudioFrame::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
833inline
834void
835AudioFrame::Mute() const
836{
837  memset(_payloadData, 0, _payloadDataLengthInSamples * sizeof(WebRtc_Word16));
838}
839
840inline
841AudioFrame&
842AudioFrame::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
871inline
872AudioFrame&
873AudioFrame::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
888inline
889AudioFrame&
890AudioFrame::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
930inline
931AudioFrame&
932AudioFrame::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
1003inline
1004AudioFrame&
1005AudioFrame::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