1/*
2 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#ifndef MODULE_COMMON_TYPES_H
12#define MODULE_COMMON_TYPES_H
13
14#include <assert.h>
15#include <string.h>  // memcpy
16
17#include <algorithm>
18
19#include "webrtc/base/constructormagic.h"
20#include "webrtc/common_types.h"
21#include "webrtc/typedefs.h"
22
23namespace webrtc {
24
25struct RTPAudioHeader {
26  uint8_t numEnergy;                  // number of valid entries in arrOfEnergy
27  uint8_t arrOfEnergy[kRtpCsrcSize];  // one energy byte (0-9) per channel
28  bool isCNG;                         // is this CNG
29  uint8_t channel;                    // number of channels 2 = stereo
30};
31
32const int16_t kNoPictureId = -1;
33const int16_t kNoTl0PicIdx = -1;
34const uint8_t kNoTemporalIdx = 0xFF;
35const int kNoKeyIdx = -1;
36
37struct RTPVideoHeaderVP8 {
38  void InitRTPVideoHeaderVP8() {
39    nonReference = false;
40    pictureId = kNoPictureId;
41    tl0PicIdx = kNoTl0PicIdx;
42    temporalIdx = kNoTemporalIdx;
43    layerSync = false;
44    keyIdx = kNoKeyIdx;
45    partitionId = 0;
46    beginningOfPartition = false;
47  }
48
49  bool nonReference;          // Frame is discardable.
50  int16_t pictureId;          // Picture ID index, 15 bits;
51                              // kNoPictureId if PictureID does not exist.
52  int16_t tl0PicIdx;          // TL0PIC_IDX, 8 bits;
53                              // kNoTl0PicIdx means no value provided.
54  uint8_t temporalIdx;        // Temporal layer index, or kNoTemporalIdx.
55  bool layerSync;             // This frame is a layer sync frame.
56                              // Disabled if temporalIdx == kNoTemporalIdx.
57  int keyIdx;                 // 5 bits; kNoKeyIdx means not used.
58  int partitionId;            // VP8 partition ID
59  bool beginningOfPartition;  // True if this packet is the first
60                              // in a VP8 partition. Otherwise false
61};
62
63struct RTPVideoHeaderH264 {
64  bool stap_a;
65  bool single_nalu;
66};
67
68union RTPVideoTypeHeader {
69  RTPVideoHeaderVP8 VP8;
70  RTPVideoHeaderH264 H264;
71};
72
73enum RtpVideoCodecTypes {
74  kRtpVideoNone,
75  kRtpVideoGeneric,
76  kRtpVideoVp8,
77  kRtpVideoH264
78};
79struct RTPVideoHeader {
80  uint16_t width;  // size
81  uint16_t height;
82
83  bool isFirstPacket;    // first packet in frame
84  uint8_t simulcastIdx;  // Index if the simulcast encoder creating
85                         // this frame, 0 if not using simulcast.
86  RtpVideoCodecTypes codec;
87  RTPVideoTypeHeader codecHeader;
88};
89union RTPTypeHeader {
90  RTPAudioHeader Audio;
91  RTPVideoHeader Video;
92};
93
94struct WebRtcRTPHeader {
95  RTPHeader header;
96  FrameType frameType;
97  RTPTypeHeader type;
98  // NTP time of the capture time in local timebase in milliseconds.
99  int64_t ntp_time_ms;
100};
101
102class RTPFragmentationHeader {
103 public:
104  RTPFragmentationHeader()
105      : fragmentationVectorSize(0),
106        fragmentationOffset(NULL),
107        fragmentationLength(NULL),
108        fragmentationTimeDiff(NULL),
109        fragmentationPlType(NULL) {};
110
111  ~RTPFragmentationHeader() {
112    delete[] fragmentationOffset;
113    delete[] fragmentationLength;
114    delete[] fragmentationTimeDiff;
115    delete[] fragmentationPlType;
116  }
117
118  void CopyFrom(const RTPFragmentationHeader& src) {
119    if (this == &src) {
120      return;
121    }
122
123    if (src.fragmentationVectorSize != fragmentationVectorSize) {
124      // new size of vectors
125
126      // delete old
127      delete[] fragmentationOffset;
128      fragmentationOffset = NULL;
129      delete[] fragmentationLength;
130      fragmentationLength = NULL;
131      delete[] fragmentationTimeDiff;
132      fragmentationTimeDiff = NULL;
133      delete[] fragmentationPlType;
134      fragmentationPlType = NULL;
135
136      if (src.fragmentationVectorSize > 0) {
137        // allocate new
138        if (src.fragmentationOffset) {
139          fragmentationOffset = new uint32_t[src.fragmentationVectorSize];
140        }
141        if (src.fragmentationLength) {
142          fragmentationLength = new uint32_t[src.fragmentationVectorSize];
143        }
144        if (src.fragmentationTimeDiff) {
145          fragmentationTimeDiff = new uint16_t[src.fragmentationVectorSize];
146        }
147        if (src.fragmentationPlType) {
148          fragmentationPlType = new uint8_t[src.fragmentationVectorSize];
149        }
150      }
151      // set new size
152      fragmentationVectorSize = src.fragmentationVectorSize;
153    }
154
155    if (src.fragmentationVectorSize > 0) {
156      // copy values
157      if (src.fragmentationOffset) {
158        memcpy(fragmentationOffset, src.fragmentationOffset,
159               src.fragmentationVectorSize * sizeof(uint32_t));
160      }
161      if (src.fragmentationLength) {
162        memcpy(fragmentationLength, src.fragmentationLength,
163               src.fragmentationVectorSize * sizeof(uint32_t));
164      }
165      if (src.fragmentationTimeDiff) {
166        memcpy(fragmentationTimeDiff, src.fragmentationTimeDiff,
167               src.fragmentationVectorSize * sizeof(uint16_t));
168      }
169      if (src.fragmentationPlType) {
170        memcpy(fragmentationPlType, src.fragmentationPlType,
171               src.fragmentationVectorSize * sizeof(uint8_t));
172      }
173    }
174  }
175
176  void VerifyAndAllocateFragmentationHeader(const uint16_t size) {
177    if (fragmentationVectorSize < size) {
178      uint16_t oldVectorSize = fragmentationVectorSize;
179      {
180        // offset
181        uint32_t* oldOffsets = fragmentationOffset;
182        fragmentationOffset = new uint32_t[size];
183        memset(fragmentationOffset + oldVectorSize, 0,
184               sizeof(uint32_t) * (size - oldVectorSize));
185        // copy old values
186        memcpy(fragmentationOffset, oldOffsets,
187               sizeof(uint32_t) * oldVectorSize);
188        delete[] oldOffsets;
189      }
190      // length
191      {
192        uint32_t* oldLengths = fragmentationLength;
193        fragmentationLength = new uint32_t[size];
194        memset(fragmentationLength + oldVectorSize, 0,
195               sizeof(uint32_t) * (size - oldVectorSize));
196        memcpy(fragmentationLength, oldLengths,
197               sizeof(uint32_t) * oldVectorSize);
198        delete[] oldLengths;
199      }
200      // time diff
201      {
202        uint16_t* oldTimeDiffs = fragmentationTimeDiff;
203        fragmentationTimeDiff = new uint16_t[size];
204        memset(fragmentationTimeDiff + oldVectorSize, 0,
205               sizeof(uint16_t) * (size - oldVectorSize));
206        memcpy(fragmentationTimeDiff, oldTimeDiffs,
207               sizeof(uint16_t) * oldVectorSize);
208        delete[] oldTimeDiffs;
209      }
210      // payload type
211      {
212        uint8_t* oldTimePlTypes = fragmentationPlType;
213        fragmentationPlType = new uint8_t[size];
214        memset(fragmentationPlType + oldVectorSize, 0,
215               sizeof(uint8_t) * (size - oldVectorSize));
216        memcpy(fragmentationPlType, oldTimePlTypes,
217               sizeof(uint8_t) * oldVectorSize);
218        delete[] oldTimePlTypes;
219      }
220      fragmentationVectorSize = size;
221    }
222  }
223
224  uint16_t fragmentationVectorSize;  // Number of fragmentations
225  uint32_t* fragmentationOffset;    // Offset of pointer to data for each fragm.
226  uint32_t* fragmentationLength;    // Data size for each fragmentation
227  uint16_t* fragmentationTimeDiff;  // Timestamp difference relative "now" for
228                                    // each fragmentation
229  uint8_t* fragmentationPlType;     // Payload type of each fragmentation
230
231 private:
232  DISALLOW_COPY_AND_ASSIGN(RTPFragmentationHeader);
233};
234
235struct RTCPVoIPMetric {
236  // RFC 3611 4.7
237  uint8_t lossRate;
238  uint8_t discardRate;
239  uint8_t burstDensity;
240  uint8_t gapDensity;
241  uint16_t burstDuration;
242  uint16_t gapDuration;
243  uint16_t roundTripDelay;
244  uint16_t endSystemDelay;
245  uint8_t signalLevel;
246  uint8_t noiseLevel;
247  uint8_t RERL;
248  uint8_t Gmin;
249  uint8_t Rfactor;
250  uint8_t extRfactor;
251  uint8_t MOSLQ;
252  uint8_t MOSCQ;
253  uint8_t RXconfig;
254  uint16_t JBnominal;
255  uint16_t JBmax;
256  uint16_t JBabsMax;
257};
258
259// Types for the FEC packet masks. The type |kFecMaskRandom| is based on a
260// random loss model. The type |kFecMaskBursty| is based on a bursty/consecutive
261// loss model. The packet masks are defined in
262// modules/rtp_rtcp/fec_private_tables_random(bursty).h
263enum FecMaskType {
264  kFecMaskRandom,
265  kFecMaskBursty,
266};
267
268// Struct containing forward error correction settings.
269struct FecProtectionParams {
270  int fec_rate;
271  bool use_uep_protection;
272  int max_fec_frames;
273  FecMaskType fec_mask_type;
274};
275
276// Interface used by the CallStats class to distribute call statistics.
277// Callbacks will be triggered as soon as the class has been registered to a
278// CallStats object using RegisterStatsObserver.
279class CallStatsObserver {
280 public:
281  virtual void OnRttUpdate(uint32_t rtt_ms) = 0;
282
283  virtual ~CallStatsObserver() {}
284};
285
286// class describing a complete, or parts of an encoded frame.
287class EncodedVideoData {
288 public:
289  EncodedVideoData()
290      : payloadType(0),
291        timeStamp(0),
292        renderTimeMs(0),
293        encodedWidth(0),
294        encodedHeight(0),
295        completeFrame(false),
296        missingFrame(false),
297        payloadData(NULL),
298        payloadSize(0),
299        bufferSize(0),
300        fragmentationHeader(),
301        frameType(kVideoFrameDelta),
302        codec(kVideoCodecUnknown) {};
303
304  EncodedVideoData(const EncodedVideoData& data) {
305    payloadType = data.payloadType;
306    timeStamp = data.timeStamp;
307    renderTimeMs = data.renderTimeMs;
308    encodedWidth = data.encodedWidth;
309    encodedHeight = data.encodedHeight;
310    completeFrame = data.completeFrame;
311    missingFrame = data.missingFrame;
312    payloadSize = data.payloadSize;
313    fragmentationHeader.CopyFrom(data.fragmentationHeader);
314    frameType = data.frameType;
315    codec = data.codec;
316    if (data.payloadSize > 0) {
317      payloadData = new uint8_t[data.payloadSize];
318      memcpy(payloadData, data.payloadData, data.payloadSize);
319    } else {
320      payloadData = NULL;
321    }
322  }
323
324  ~EncodedVideoData() {
325    delete[] payloadData;
326  };
327
328  EncodedVideoData& operator=(const EncodedVideoData& data) {
329    if (this == &data) {
330      return *this;
331    }
332    payloadType = data.payloadType;
333    timeStamp = data.timeStamp;
334    renderTimeMs = data.renderTimeMs;
335    encodedWidth = data.encodedWidth;
336    encodedHeight = data.encodedHeight;
337    completeFrame = data.completeFrame;
338    missingFrame = data.missingFrame;
339    payloadSize = data.payloadSize;
340    fragmentationHeader.CopyFrom(data.fragmentationHeader);
341    frameType = data.frameType;
342    codec = data.codec;
343    if (data.payloadSize > 0) {
344      delete[] payloadData;
345      payloadData = new uint8_t[data.payloadSize];
346      memcpy(payloadData, data.payloadData, data.payloadSize);
347      bufferSize = data.payloadSize;
348    }
349    return *this;
350  };
351  void VerifyAndAllocate(const uint32_t size) {
352    if (bufferSize < size) {
353      uint8_t* oldPayload = payloadData;
354      payloadData = new uint8_t[size];
355      memcpy(payloadData, oldPayload, sizeof(uint8_t) * payloadSize);
356
357      bufferSize = size;
358      delete[] oldPayload;
359    }
360  }
361
362  uint8_t payloadType;
363  uint32_t timeStamp;
364  int64_t renderTimeMs;
365  uint32_t encodedWidth;
366  uint32_t encodedHeight;
367  bool completeFrame;
368  bool missingFrame;
369  uint8_t* payloadData;
370  uint32_t payloadSize;
371  uint32_t bufferSize;
372  RTPFragmentationHeader fragmentationHeader;
373  FrameType frameType;
374  VideoCodecType codec;
375};
376
377struct VideoContentMetrics {
378  VideoContentMetrics()
379      : motion_magnitude(0.0f),
380        spatial_pred_err(0.0f),
381        spatial_pred_err_h(0.0f),
382        spatial_pred_err_v(0.0f) {}
383
384  void Reset() {
385    motion_magnitude = 0.0f;
386    spatial_pred_err = 0.0f;
387    spatial_pred_err_h = 0.0f;
388    spatial_pred_err_v = 0.0f;
389  }
390  float motion_magnitude;
391  float spatial_pred_err;
392  float spatial_pred_err_h;
393  float spatial_pred_err_v;
394};
395
396/*************************************************
397 *
398 * VideoFrame class
399 *
400 * The VideoFrame class allows storing and
401 * handling of video frames.
402 *
403 *
404 *************************************************/
405class VideoFrame {
406 public:
407  VideoFrame();
408  ~VideoFrame();
409  /**
410  * Verifies that current allocated buffer size is larger than or equal to the
411  * input size.
412  * If the current buffer size is smaller, a new allocation is made and the old
413  * buffer data
414  * is copied to the new buffer.
415  * Buffer size is updated to minimumSize.
416  */
417  int32_t VerifyAndAllocate(const uint32_t minimumSize);
418  /**
419  *    Update length of data buffer in frame. Function verifies that new length
420  * is less or
421  *    equal to allocated size.
422  */
423  int32_t SetLength(const uint32_t newLength);
424  /*
425  *    Swap buffer and size data
426  */
427  int32_t Swap(uint8_t*& newMemory, uint32_t& newLength, uint32_t& newSize);
428  /*
429  *    Swap buffer and size data
430  */
431  int32_t SwapFrame(VideoFrame& videoFrame);
432  /**
433  *    Copy buffer: If newLength is bigger than allocated size, a new buffer of
434  * size length
435  *    is allocated.
436  */
437  int32_t CopyFrame(const VideoFrame& videoFrame);
438  /**
439  *    Copy buffer: If newLength is bigger than allocated size, a new buffer of
440  * size length
441  *    is allocated.
442  */
443  int32_t CopyFrame(uint32_t length, const uint8_t* sourceBuffer);
444  /**
445  *    Delete VideoFrame and resets members to zero
446  */
447  void Free();
448  /**
449  *   Set frame timestamp (90kHz)
450  */
451  void SetTimeStamp(const uint32_t timeStamp) { _timeStamp = timeStamp; }
452  /**
453  *   Get pointer to frame buffer
454  */
455  uint8_t* Buffer() const { return _buffer; }
456
457  uint8_t*& Buffer() { return _buffer; }
458
459  /**
460  *   Get allocated buffer size
461  */
462  uint32_t Size() const { return _bufferSize; }
463  /**
464  *   Get frame length
465  */
466  uint32_t Length() const { return _bufferLength; }
467  /**
468  *   Get frame timestamp (90kHz)
469  */
470  uint32_t TimeStamp() const { return _timeStamp; }
471  /**
472  *   Get frame width
473  */
474  uint32_t Width() const { return _width; }
475  /**
476  *   Get frame height
477  */
478  uint32_t Height() const { return _height; }
479  /**
480  *   Set frame width
481  */
482  void SetWidth(const uint32_t width) { _width = width; }
483  /**
484  *   Set frame height
485  */
486  void SetHeight(const uint32_t height) { _height = height; }
487  /**
488  *   Set render time in miliseconds
489  */
490  void SetRenderTime(const int64_t renderTimeMs) {
491    _renderTimeMs = renderTimeMs;
492  }
493  /**
494  *  Get render time in miliseconds
495  */
496  int64_t RenderTimeMs() const { return _renderTimeMs; }
497
498 private:
499  void Set(uint8_t* buffer, uint32_t size, uint32_t length, uint32_t timeStamp);
500
501  uint8_t* _buffer;        // Pointer to frame buffer
502  uint32_t _bufferSize;    // Allocated buffer size
503  uint32_t _bufferLength;  // Length (in bytes) of buffer
504  uint32_t _timeStamp;     // Timestamp of frame (90kHz)
505  uint32_t _width;
506  uint32_t _height;
507  int64_t _renderTimeMs;
508};  // end of VideoFrame class declaration
509
510// inline implementation of VideoFrame class:
511inline VideoFrame::VideoFrame()
512    : _buffer(0),
513      _bufferSize(0),
514      _bufferLength(0),
515      _timeStamp(0),
516      _width(0),
517      _height(0),
518      _renderTimeMs(0) {
519  //
520}
521inline VideoFrame::~VideoFrame() {
522  if (_buffer) {
523    delete[] _buffer;
524    _buffer = NULL;
525  }
526}
527
528inline int32_t VideoFrame::VerifyAndAllocate(const uint32_t minimumSize) {
529  if (minimumSize < 1) {
530    return -1;
531  }
532  if (minimumSize > _bufferSize) {
533    // create buffer of sufficient size
534    uint8_t* newBufferBuffer = new uint8_t[minimumSize];
535    if (_buffer) {
536      // copy old data
537      memcpy(newBufferBuffer, _buffer, _bufferSize);
538      delete[] _buffer;
539    } else {
540      memset(newBufferBuffer, 0, minimumSize * sizeof(uint8_t));
541    }
542    _buffer = newBufferBuffer;
543    _bufferSize = minimumSize;
544  }
545  return 0;
546}
547
548inline int32_t VideoFrame::SetLength(const uint32_t newLength) {
549  if (newLength > _bufferSize) {  // can't accomodate new value
550    return -1;
551  }
552  _bufferLength = newLength;
553  return 0;
554}
555
556inline int32_t VideoFrame::SwapFrame(VideoFrame& videoFrame) {
557  uint32_t tmpTimeStamp = _timeStamp;
558  uint32_t tmpWidth = _width;
559  uint32_t tmpHeight = _height;
560  int64_t tmpRenderTime = _renderTimeMs;
561
562  _timeStamp = videoFrame._timeStamp;
563  _width = videoFrame._width;
564  _height = videoFrame._height;
565  _renderTimeMs = videoFrame._renderTimeMs;
566
567  videoFrame._timeStamp = tmpTimeStamp;
568  videoFrame._width = tmpWidth;
569  videoFrame._height = tmpHeight;
570  videoFrame._renderTimeMs = tmpRenderTime;
571
572  return Swap(videoFrame._buffer, videoFrame._bufferLength,
573              videoFrame._bufferSize);
574}
575
576inline int32_t VideoFrame::Swap(uint8_t*& newMemory, uint32_t& newLength,
577                                uint32_t& newSize) {
578  uint8_t* tmpBuffer = _buffer;
579  uint32_t tmpLength = _bufferLength;
580  uint32_t tmpSize = _bufferSize;
581  _buffer = newMemory;
582  _bufferLength = newLength;
583  _bufferSize = newSize;
584  newMemory = tmpBuffer;
585  newLength = tmpLength;
586  newSize = tmpSize;
587  return 0;
588}
589
590inline int32_t VideoFrame::CopyFrame(uint32_t length,
591                                     const uint8_t* sourceBuffer) {
592  if (length > _bufferSize) {
593    int32_t ret = VerifyAndAllocate(length);
594    if (ret < 0) {
595      return ret;
596    }
597  }
598  memcpy(_buffer, sourceBuffer, length);
599  _bufferLength = length;
600  return 0;
601}
602
603inline int32_t VideoFrame::CopyFrame(const VideoFrame& videoFrame) {
604  if (CopyFrame(videoFrame.Length(), videoFrame.Buffer()) != 0) {
605    return -1;
606  }
607  _timeStamp = videoFrame._timeStamp;
608  _width = videoFrame._width;
609  _height = videoFrame._height;
610  _renderTimeMs = videoFrame._renderTimeMs;
611  return 0;
612}
613
614inline void VideoFrame::Free() {
615  _timeStamp = 0;
616  _bufferLength = 0;
617  _bufferSize = 0;
618  _height = 0;
619  _width = 0;
620  _renderTimeMs = 0;
621
622  if (_buffer) {
623    delete[] _buffer;
624    _buffer = NULL;
625  }
626}
627
628/* This class holds up to 60 ms of super-wideband (32 kHz) stereo audio. It
629 * allows for adding and subtracting frames while keeping track of the resulting
630 * states.
631 *
632 * Notes
633 * - The total number of samples in |data_| is
634 *   samples_per_channel_ * num_channels_
635 *
636 * - Stereo data is interleaved starting with the left channel.
637 *
638 * - The +operator assume that you would never add exactly opposite frames when
639 *   deciding the resulting state. To do this use the -operator.
640 */
641class AudioFrame {
642 public:
643  // Stereo, 32 kHz, 60 ms (2 * 32 * 60)
644  static const int kMaxDataSizeSamples = 3840;
645
646  enum VADActivity {
647    kVadActive = 0,
648    kVadPassive = 1,
649    kVadUnknown = 2
650  };
651  enum SpeechType {
652    kNormalSpeech = 0,
653    kPLC = 1,
654    kCNG = 2,
655    kPLCCNG = 3,
656    kUndefined = 4
657  };
658
659  AudioFrame();
660  virtual ~AudioFrame() {}
661
662  // Resets all members to their default state (except does not modify the
663  // contents of |data_|).
664  void Reset();
665
666  // |interleaved_| is not changed by this method.
667  void UpdateFrame(int id, uint32_t timestamp, const int16_t* data,
668                   int samples_per_channel, int sample_rate_hz,
669                   SpeechType speech_type, VADActivity vad_activity,
670                   int num_channels = 1, uint32_t energy = -1);
671
672  AudioFrame& Append(const AudioFrame& rhs);
673
674  void CopyFrom(const AudioFrame& src);
675
676  void Mute();
677
678  AudioFrame& operator>>=(const int rhs);
679  AudioFrame& operator+=(const AudioFrame& rhs);
680  AudioFrame& operator-=(const AudioFrame& rhs);
681
682  int id_;
683  // RTP timestamp of the first sample in the AudioFrame.
684  uint32_t timestamp_;
685  // Time since the first frame in milliseconds.
686  // -1 represents an uninitialized value.
687  int64_t elapsed_time_ms_;
688  // NTP time of the estimated capture time in local timebase in milliseconds.
689  // -1 represents an uninitialized value.
690  int64_t ntp_time_ms_;
691  int16_t data_[kMaxDataSizeSamples];
692  int samples_per_channel_;
693  int sample_rate_hz_;
694  int num_channels_;
695  SpeechType speech_type_;
696  VADActivity vad_activity_;
697  // Note that there is no guarantee that |energy_| is correct. Any user of this
698  // member must verify that the value is correct.
699  // TODO(henrike) Remove |energy_|.
700  // See https://code.google.com/p/webrtc/issues/detail?id=3315.
701  uint32_t energy_;
702  bool interleaved_;
703
704 private:
705  DISALLOW_COPY_AND_ASSIGN(AudioFrame);
706};
707
708inline AudioFrame::AudioFrame()
709    : data_() {
710  Reset();
711}
712
713inline void AudioFrame::Reset() {
714  id_ = -1;
715  // TODO(wu): Zero is a valid value for |timestamp_|. We should initialize
716  // to an invalid value, or add a new member to indicate invalidity.
717  timestamp_ = 0;
718  elapsed_time_ms_ = -1;
719  ntp_time_ms_ = -1;
720  samples_per_channel_ = 0;
721  sample_rate_hz_ = 0;
722  num_channels_ = 0;
723  speech_type_ = kUndefined;
724  vad_activity_ = kVadUnknown;
725  energy_ = 0xffffffff;
726  interleaved_ = true;
727}
728
729inline void AudioFrame::UpdateFrame(int id, uint32_t timestamp,
730                                    const int16_t* data,
731                                    int samples_per_channel, int sample_rate_hz,
732                                    SpeechType speech_type,
733                                    VADActivity vad_activity, int num_channels,
734                                    uint32_t energy) {
735  id_ = id;
736  timestamp_ = timestamp;
737  samples_per_channel_ = samples_per_channel;
738  sample_rate_hz_ = sample_rate_hz;
739  speech_type_ = speech_type;
740  vad_activity_ = vad_activity;
741  num_channels_ = num_channels;
742  energy_ = energy;
743
744  const int length = samples_per_channel * num_channels;
745  assert(length <= kMaxDataSizeSamples && length >= 0);
746  if (data != NULL) {
747    memcpy(data_, data, sizeof(int16_t) * length);
748  } else {
749    memset(data_, 0, sizeof(int16_t) * length);
750  }
751}
752
753inline void AudioFrame::CopyFrom(const AudioFrame& src) {
754  if (this == &src) return;
755
756  id_ = src.id_;
757  timestamp_ = src.timestamp_;
758  elapsed_time_ms_ = src.elapsed_time_ms_;
759  ntp_time_ms_ = src.ntp_time_ms_;
760  samples_per_channel_ = src.samples_per_channel_;
761  sample_rate_hz_ = src.sample_rate_hz_;
762  speech_type_ = src.speech_type_;
763  vad_activity_ = src.vad_activity_;
764  num_channels_ = src.num_channels_;
765  energy_ = src.energy_;
766  interleaved_ = src.interleaved_;
767
768  const int length = samples_per_channel_ * num_channels_;
769  assert(length <= kMaxDataSizeSamples && length >= 0);
770  memcpy(data_, src.data_, sizeof(int16_t) * length);
771}
772
773inline void AudioFrame::Mute() {
774  memset(data_, 0, samples_per_channel_ * num_channels_ * sizeof(int16_t));
775}
776
777inline AudioFrame& AudioFrame::operator>>=(const int rhs) {
778  assert((num_channels_ > 0) && (num_channels_ < 3));
779  if ((num_channels_ > 2) || (num_channels_ < 1)) return *this;
780
781  for (int i = 0; i < samples_per_channel_ * num_channels_; i++) {
782    data_[i] = static_cast<int16_t>(data_[i] >> rhs);
783  }
784  return *this;
785}
786
787inline AudioFrame& AudioFrame::Append(const AudioFrame& rhs) {
788  // Sanity check
789  assert((num_channels_ > 0) && (num_channels_ < 3));
790  assert(interleaved_ == rhs.interleaved_);
791  if ((num_channels_ > 2) || (num_channels_ < 1)) return *this;
792  if (num_channels_ != rhs.num_channels_) return *this;
793
794  if ((vad_activity_ == kVadActive) || rhs.vad_activity_ == kVadActive) {
795    vad_activity_ = kVadActive;
796  } else if (vad_activity_ == kVadUnknown || rhs.vad_activity_ == kVadUnknown) {
797    vad_activity_ = kVadUnknown;
798  }
799  if (speech_type_ != rhs.speech_type_) {
800    speech_type_ = kUndefined;
801  }
802
803  int offset = samples_per_channel_ * num_channels_;
804  for (int i = 0; i < rhs.samples_per_channel_ * rhs.num_channels_; i++) {
805    data_[offset + i] = rhs.data_[i];
806  }
807  samples_per_channel_ += rhs.samples_per_channel_;
808  return *this;
809}
810
811inline AudioFrame& AudioFrame::operator+=(const AudioFrame& rhs) {
812  // Sanity check
813  assert((num_channels_ > 0) && (num_channels_ < 3));
814  assert(interleaved_ == rhs.interleaved_);
815  if ((num_channels_ > 2) || (num_channels_ < 1)) return *this;
816  if (num_channels_ != rhs.num_channels_) return *this;
817
818  bool noPrevData = false;
819  if (samples_per_channel_ != rhs.samples_per_channel_) {
820    if (samples_per_channel_ == 0) {
821      // special case we have no data to start with
822      samples_per_channel_ = rhs.samples_per_channel_;
823      noPrevData = true;
824    } else {
825      return *this;
826    }
827  }
828
829  if ((vad_activity_ == kVadActive) || rhs.vad_activity_ == kVadActive) {
830    vad_activity_ = kVadActive;
831  } else if (vad_activity_ == kVadUnknown || rhs.vad_activity_ == kVadUnknown) {
832    vad_activity_ = kVadUnknown;
833  }
834
835  if (speech_type_ != rhs.speech_type_) speech_type_ = kUndefined;
836
837  if (noPrevData) {
838    memcpy(data_, rhs.data_,
839           sizeof(int16_t) * rhs.samples_per_channel_ * num_channels_);
840  } else {
841    // IMPROVEMENT this can be done very fast in assembly
842    for (int i = 0; i < samples_per_channel_ * num_channels_; i++) {
843      int32_t wrapGuard =
844          static_cast<int32_t>(data_[i]) + static_cast<int32_t>(rhs.data_[i]);
845      if (wrapGuard < -32768) {
846        data_[i] = -32768;
847      } else if (wrapGuard > 32767) {
848        data_[i] = 32767;
849      } else {
850        data_[i] = (int16_t)wrapGuard;
851      }
852    }
853  }
854  energy_ = 0xffffffff;
855  return *this;
856}
857
858inline AudioFrame& AudioFrame::operator-=(const AudioFrame& rhs) {
859  // Sanity check
860  assert((num_channels_ > 0) && (num_channels_ < 3));
861  assert(interleaved_ == rhs.interleaved_);
862  if ((num_channels_ > 2) || (num_channels_ < 1)) return *this;
863
864  if ((samples_per_channel_ != rhs.samples_per_channel_) ||
865      (num_channels_ != rhs.num_channels_)) {
866    return *this;
867  }
868  if ((vad_activity_ != kVadPassive) || rhs.vad_activity_ != kVadPassive) {
869    vad_activity_ = kVadUnknown;
870  }
871  speech_type_ = kUndefined;
872
873  for (int i = 0; i < samples_per_channel_ * num_channels_; i++) {
874    int32_t wrapGuard =
875        static_cast<int32_t>(data_[i]) - static_cast<int32_t>(rhs.data_[i]);
876    if (wrapGuard < -32768) {
877      data_[i] = -32768;
878    } else if (wrapGuard > 32767) {
879      data_[i] = 32767;
880    } else {
881      data_[i] = (int16_t)wrapGuard;
882    }
883  }
884  energy_ = 0xffffffff;
885  return *this;
886}
887
888inline bool IsNewerSequenceNumber(uint16_t sequence_number,
889                                  uint16_t prev_sequence_number) {
890  return sequence_number != prev_sequence_number &&
891         static_cast<uint16_t>(sequence_number - prev_sequence_number) < 0x8000;
892}
893
894inline bool IsNewerTimestamp(uint32_t timestamp, uint32_t prev_timestamp) {
895  return timestamp != prev_timestamp &&
896         static_cast<uint32_t>(timestamp - prev_timestamp) < 0x80000000;
897}
898
899inline uint16_t LatestSequenceNumber(uint16_t sequence_number1,
900                                     uint16_t sequence_number2) {
901  return IsNewerSequenceNumber(sequence_number1, sequence_number2)
902             ? sequence_number1
903             : sequence_number2;
904}
905
906inline uint32_t LatestTimestamp(uint32_t timestamp1, uint32_t timestamp2) {
907  return IsNewerTimestamp(timestamp1, timestamp2) ? timestamp1 : timestamp2;
908}
909
910}  // namespace webrtc
911
912#endif  // MODULE_COMMON_TYPES_H
913