2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
11 #ifndef MODULE_COMMON_TYPES_H
12 #define MODULE_COMMON_TYPES_H
15 #include <string.h> // memcpy
19 #include "webrtc/common_types.h"
20 #include "webrtc/system_wrappers/interface/constructor_magic.h"
21 #include "webrtc/typedefs.h"
24 // Remove warning "new behavior: elements of array will be default initialized".
25 #pragma warning(disable : 4351)
30 struct RTPAudioHeader {
31 uint8_t numEnergy; // number of valid entries in arrOfEnergy
32 uint8_t arrOfEnergy[kRtpCsrcSize]; // one energy byte (0-9) per channel
33 bool isCNG; // is this CNG
34 uint8_t channel; // number of channels 2 = stereo
53 struct RTPVideoHeaderVP8 {
54 void InitRTPVideoHeaderVP8() {
56 pictureId = kNoPictureId;
57 tl0PicIdx = kNoTl0PicIdx;
58 temporalIdx = kNoTemporalIdx;
62 beginningOfPartition = false;
65 bool nonReference; // Frame is discardable.
66 int16_t pictureId; // Picture ID index, 15 bits;
67 // kNoPictureId if PictureID does not exist.
68 int16_t tl0PicIdx; // TL0PIC_IDX, 8 bits;
69 // kNoTl0PicIdx means no value provided.
70 int8_t temporalIdx; // Temporal layer index, or kNoTemporalIdx.
71 bool layerSync; // This frame is a layer sync frame.
72 // Disabled if temporalIdx == kNoTemporalIdx.
73 int keyIdx; // 5 bits; kNoKeyIdx means not used.
74 int partitionId; // VP8 partition ID
75 bool beginningOfPartition; // True if this packet is the first
76 // in a VP8 partition. Otherwise false
78 union RTPVideoTypeHeader {
79 RTPVideoHeaderVP8 VP8;
82 enum RtpVideoCodecTypes {
87 struct RTPVideoHeader {
88 uint16_t width; // size
91 bool isFirstPacket; // first packet in frame
92 uint8_t simulcastIdx; // Index if the simulcast encoder creating
93 // this frame, 0 if not using simulcast.
94 RtpVideoCodecTypes codec;
95 RTPVideoTypeHeader codecHeader;
102 struct WebRtcRTPHeader {
106 // NTP time of the capture time in local timebase in milliseconds.
110 class RTPFragmentationHeader {
112 RTPFragmentationHeader()
113 : fragmentationVectorSize(0),
114 fragmentationOffset(NULL),
115 fragmentationLength(NULL),
116 fragmentationTimeDiff(NULL),
117 fragmentationPlType(NULL) {};
119 ~RTPFragmentationHeader() {
120 delete[] fragmentationOffset;
121 delete[] fragmentationLength;
122 delete[] fragmentationTimeDiff;
123 delete[] fragmentationPlType;
126 void CopyFrom(const RTPFragmentationHeader& src) {
131 if (src.fragmentationVectorSize != fragmentationVectorSize) {
132 // new size of vectors
135 delete[] fragmentationOffset;
136 fragmentationOffset = NULL;
137 delete[] fragmentationLength;
138 fragmentationLength = NULL;
139 delete[] fragmentationTimeDiff;
140 fragmentationTimeDiff = NULL;
141 delete[] fragmentationPlType;
142 fragmentationPlType = NULL;
144 if (src.fragmentationVectorSize > 0) {
146 if (src.fragmentationOffset) {
147 fragmentationOffset = new uint32_t[src.fragmentationVectorSize];
149 if (src.fragmentationLength) {
150 fragmentationLength = new uint32_t[src.fragmentationVectorSize];
152 if (src.fragmentationTimeDiff) {
153 fragmentationTimeDiff = new uint16_t[src.fragmentationVectorSize];
155 if (src.fragmentationPlType) {
156 fragmentationPlType = new uint8_t[src.fragmentationVectorSize];
160 fragmentationVectorSize = src.fragmentationVectorSize;
163 if (src.fragmentationVectorSize > 0) {
165 if (src.fragmentationOffset) {
166 memcpy(fragmentationOffset, src.fragmentationOffset,
167 src.fragmentationVectorSize * sizeof(uint32_t));
169 if (src.fragmentationLength) {
170 memcpy(fragmentationLength, src.fragmentationLength,
171 src.fragmentationVectorSize * sizeof(uint32_t));
173 if (src.fragmentationTimeDiff) {
174 memcpy(fragmentationTimeDiff, src.fragmentationTimeDiff,
175 src.fragmentationVectorSize * sizeof(uint16_t));
177 if (src.fragmentationPlType) {
178 memcpy(fragmentationPlType, src.fragmentationPlType,
179 src.fragmentationVectorSize * sizeof(uint8_t));
184 void VerifyAndAllocateFragmentationHeader(const uint16_t size) {
185 if (fragmentationVectorSize < size) {
186 uint16_t oldVectorSize = fragmentationVectorSize;
189 uint32_t* oldOffsets = fragmentationOffset;
190 fragmentationOffset = new uint32_t[size];
191 memset(fragmentationOffset + oldVectorSize, 0,
192 sizeof(uint32_t) * (size - oldVectorSize));
194 memcpy(fragmentationOffset, oldOffsets,
195 sizeof(uint32_t) * oldVectorSize);
200 uint32_t* oldLengths = fragmentationLength;
201 fragmentationLength = new uint32_t[size];
202 memset(fragmentationLength + oldVectorSize, 0,
203 sizeof(uint32_t) * (size - oldVectorSize));
204 memcpy(fragmentationLength, oldLengths,
205 sizeof(uint32_t) * oldVectorSize);
210 uint16_t* oldTimeDiffs = fragmentationTimeDiff;
211 fragmentationTimeDiff = new uint16_t[size];
212 memset(fragmentationTimeDiff + oldVectorSize, 0,
213 sizeof(uint16_t) * (size - oldVectorSize));
214 memcpy(fragmentationTimeDiff, oldTimeDiffs,
215 sizeof(uint16_t) * oldVectorSize);
216 delete[] oldTimeDiffs;
220 uint8_t* oldTimePlTypes = fragmentationPlType;
221 fragmentationPlType = new uint8_t[size];
222 memset(fragmentationPlType + oldVectorSize, 0,
223 sizeof(uint8_t) * (size - oldVectorSize));
224 memcpy(fragmentationPlType, oldTimePlTypes,
225 sizeof(uint8_t) * oldVectorSize);
226 delete[] oldTimePlTypes;
228 fragmentationVectorSize = size;
232 uint16_t fragmentationVectorSize; // Number of fragmentations
233 uint32_t* fragmentationOffset; // Offset of pointer to data for each fragm.
234 uint32_t* fragmentationLength; // Data size for each fragmentation
235 uint16_t* fragmentationTimeDiff; // Timestamp difference relative "now" for
236 // each fragmentation
237 uint8_t* fragmentationPlType; // Payload type of each fragmentation
240 DISALLOW_COPY_AND_ASSIGN(RTPFragmentationHeader);
243 struct RTCPVoIPMetric {
247 uint8_t burstDensity;
249 uint16_t burstDuration;
250 uint16_t gapDuration;
251 uint16_t roundTripDelay;
252 uint16_t endSystemDelay;
267 // Types for the FEC packet masks. The type |kFecMaskRandom| is based on a
268 // random loss model. The type |kFecMaskBursty| is based on a bursty/consecutive
269 // loss model. The packet masks are defined in
270 // modules/rtp_rtcp/fec_private_tables_random(bursty).h
276 // Struct containing forward error correction settings.
277 struct FecProtectionParams {
279 bool use_uep_protection;
281 FecMaskType fec_mask_type;
284 // Interface used by the CallStats class to distribute call statistics.
285 // Callbacks will be triggered as soon as the class has been registered to a
286 // CallStats object using RegisterStatsObserver.
287 class CallStatsObserver {
289 virtual void OnRttUpdate(uint32_t rtt_ms) = 0;
291 virtual ~CallStatsObserver() {}
294 // class describing a complete, or parts of an encoded frame.
295 class EncodedVideoData {
303 completeFrame(false),
308 fragmentationHeader(),
309 frameType(kVideoFrameDelta),
310 codec(kVideoCodecUnknown) {};
312 EncodedVideoData(const EncodedVideoData& data) {
313 payloadType = data.payloadType;
314 timeStamp = data.timeStamp;
315 renderTimeMs = data.renderTimeMs;
316 encodedWidth = data.encodedWidth;
317 encodedHeight = data.encodedHeight;
318 completeFrame = data.completeFrame;
319 missingFrame = data.missingFrame;
320 payloadSize = data.payloadSize;
321 fragmentationHeader.CopyFrom(data.fragmentationHeader);
322 frameType = data.frameType;
324 if (data.payloadSize > 0) {
325 payloadData = new uint8_t[data.payloadSize];
326 memcpy(payloadData, data.payloadData, data.payloadSize);
332 ~EncodedVideoData() {
333 delete[] payloadData;
336 EncodedVideoData& operator=(const EncodedVideoData& data) {
340 payloadType = data.payloadType;
341 timeStamp = data.timeStamp;
342 renderTimeMs = data.renderTimeMs;
343 encodedWidth = data.encodedWidth;
344 encodedHeight = data.encodedHeight;
345 completeFrame = data.completeFrame;
346 missingFrame = data.missingFrame;
347 payloadSize = data.payloadSize;
348 fragmentationHeader.CopyFrom(data.fragmentationHeader);
349 frameType = data.frameType;
351 if (data.payloadSize > 0) {
352 delete[] payloadData;
353 payloadData = new uint8_t[data.payloadSize];
354 memcpy(payloadData, data.payloadData, data.payloadSize);
355 bufferSize = data.payloadSize;
359 void VerifyAndAllocate(const uint32_t size) {
360 if (bufferSize < size) {
361 uint8_t* oldPayload = payloadData;
362 payloadData = new uint8_t[size];
363 memcpy(payloadData, oldPayload, sizeof(uint8_t) * payloadSize);
372 int64_t renderTimeMs;
373 uint32_t encodedWidth;
374 uint32_t encodedHeight;
377 uint8_t* payloadData;
378 uint32_t payloadSize;
380 RTPFragmentationHeader fragmentationHeader;
382 VideoCodecType codec;
385 struct VideoContentMetrics {
386 VideoContentMetrics()
387 : motion_magnitude(0.0f),
388 spatial_pred_err(0.0f),
389 spatial_pred_err_h(0.0f),
390 spatial_pred_err_v(0.0f) {}
393 motion_magnitude = 0.0f;
394 spatial_pred_err = 0.0f;
395 spatial_pred_err_h = 0.0f;
396 spatial_pred_err_v = 0.0f;
398 float motion_magnitude;
399 float spatial_pred_err;
400 float spatial_pred_err_h;
401 float spatial_pred_err_v;
404 /*************************************************
408 * The VideoFrame class allows storing and
409 * handling of video frames.
412 *************************************************/
418 * Verifies that current allocated buffer size is larger than or equal to the
420 * If the current buffer size is smaller, a new allocation is made and the old
422 * is copied to the new buffer.
423 * Buffer size is updated to minimumSize.
425 int32_t VerifyAndAllocate(const uint32_t minimumSize);
427 * Update length of data buffer in frame. Function verifies that new length
429 * equal to allocated size.
431 int32_t SetLength(const uint32_t newLength);
433 * Swap buffer and size data
435 int32_t Swap(uint8_t*& newMemory, uint32_t& newLength, uint32_t& newSize);
437 * Swap buffer and size data
439 int32_t SwapFrame(VideoFrame& videoFrame);
441 * Copy buffer: If newLength is bigger than allocated size, a new buffer of
445 int32_t CopyFrame(const VideoFrame& videoFrame);
447 * Copy buffer: If newLength is bigger than allocated size, a new buffer of
451 int32_t CopyFrame(uint32_t length, const uint8_t* sourceBuffer);
453 * Delete VideoFrame and resets members to zero
457 * Set frame timestamp (90kHz)
459 void SetTimeStamp(const uint32_t timeStamp) { _timeStamp = timeStamp; }
461 * Get pointer to frame buffer
463 uint8_t* Buffer() const { return _buffer; }
465 uint8_t*& Buffer() { return _buffer; }
468 * Get allocated buffer size
470 uint32_t Size() const { return _bufferSize; }
474 uint32_t Length() const { return _bufferLength; }
476 * Get frame timestamp (90kHz)
478 uint32_t TimeStamp() const { return _timeStamp; }
482 uint32_t Width() const { return _width; }
486 uint32_t Height() const { return _height; }
490 void SetWidth(const uint32_t width) { _width = width; }
494 void SetHeight(const uint32_t height) { _height = height; }
496 * Set render time in miliseconds
498 void SetRenderTime(const int64_t renderTimeMs) {
499 _renderTimeMs = renderTimeMs;
502 * Get render time in miliseconds
504 int64_t RenderTimeMs() const { return _renderTimeMs; }
507 void Set(uint8_t* buffer, uint32_t size, uint32_t length, uint32_t timeStamp);
509 uint8_t* _buffer; // Pointer to frame buffer
510 uint32_t _bufferSize; // Allocated buffer size
511 uint32_t _bufferLength; // Length (in bytes) of buffer
512 uint32_t _timeStamp; // Timestamp of frame (90kHz)
515 int64_t _renderTimeMs;
516 }; // end of VideoFrame class declaration
518 // inline implementation of VideoFrame class:
519 inline VideoFrame::VideoFrame()
529 inline VideoFrame::~VideoFrame() {
536 inline int32_t VideoFrame::VerifyAndAllocate(const uint32_t minimumSize) {
537 if (minimumSize < 1) {
540 if (minimumSize > _bufferSize) {
541 // create buffer of sufficient size
542 uint8_t* newBufferBuffer = new uint8_t[minimumSize];
545 memcpy(newBufferBuffer, _buffer, _bufferSize);
548 memset(newBufferBuffer, 0, minimumSize * sizeof(uint8_t));
550 _buffer = newBufferBuffer;
551 _bufferSize = minimumSize;
556 inline int32_t VideoFrame::SetLength(const uint32_t newLength) {
557 if (newLength > _bufferSize) { // can't accomodate new value
560 _bufferLength = newLength;
564 inline int32_t VideoFrame::SwapFrame(VideoFrame& videoFrame) {
565 uint32_t tmpTimeStamp = _timeStamp;
566 uint32_t tmpWidth = _width;
567 uint32_t tmpHeight = _height;
568 int64_t tmpRenderTime = _renderTimeMs;
570 _timeStamp = videoFrame._timeStamp;
571 _width = videoFrame._width;
572 _height = videoFrame._height;
573 _renderTimeMs = videoFrame._renderTimeMs;
575 videoFrame._timeStamp = tmpTimeStamp;
576 videoFrame._width = tmpWidth;
577 videoFrame._height = tmpHeight;
578 videoFrame._renderTimeMs = tmpRenderTime;
580 return Swap(videoFrame._buffer, videoFrame._bufferLength,
581 videoFrame._bufferSize);
584 inline int32_t VideoFrame::Swap(uint8_t*& newMemory, uint32_t& newLength,
586 uint8_t* tmpBuffer = _buffer;
587 uint32_t tmpLength = _bufferLength;
588 uint32_t tmpSize = _bufferSize;
590 _bufferLength = newLength;
591 _bufferSize = newSize;
592 newMemory = tmpBuffer;
593 newLength = tmpLength;
598 inline int32_t VideoFrame::CopyFrame(uint32_t length,
599 const uint8_t* sourceBuffer) {
600 if (length > _bufferSize) {
601 int32_t ret = VerifyAndAllocate(length);
606 memcpy(_buffer, sourceBuffer, length);
607 _bufferLength = length;
611 inline int32_t VideoFrame::CopyFrame(const VideoFrame& videoFrame) {
612 if (CopyFrame(videoFrame.Length(), videoFrame.Buffer()) != 0) {
615 _timeStamp = videoFrame._timeStamp;
616 _width = videoFrame._width;
617 _height = videoFrame._height;
618 _renderTimeMs = videoFrame._renderTimeMs;
622 inline void VideoFrame::Free() {
636 /* This class holds up to 60 ms of super-wideband (32 kHz) stereo audio. It
637 * allows for adding and subtracting frames while keeping track of the resulting
641 * - The total number of samples in |data_| is
642 * samples_per_channel_ * num_channels_
644 * - Stereo data is interleaved starting with the left channel.
646 * - The +operator assume that you would never add exactly opposite frames when
647 * deciding the resulting state. To do this use the -operator.
651 // Stereo, 32 kHz, 60 ms (2 * 32 * 60)
652 static const int kMaxDataSizeSamples = 3840;
668 virtual ~AudioFrame() {}
670 // |interleaved_| is not changed by this method.
671 void UpdateFrame(int id, uint32_t timestamp, const int16_t* data,
672 int samples_per_channel, int sample_rate_hz,
673 SpeechType speech_type, VADActivity vad_activity,
674 int num_channels = 1, uint32_t energy = -1);
676 AudioFrame& Append(const AudioFrame& rhs);
678 void CopyFrom(const AudioFrame& src);
682 AudioFrame& operator>>=(const int rhs);
683 AudioFrame& operator+=(const AudioFrame& rhs);
684 AudioFrame& operator-=(const AudioFrame& rhs);
688 int16_t data_[kMaxDataSizeSamples];
689 int samples_per_channel_;
692 SpeechType speech_type_;
693 VADActivity vad_activity_;
698 DISALLOW_COPY_AND_ASSIGN(AudioFrame);
701 inline AudioFrame::AudioFrame()
705 samples_per_channel_(0),
708 speech_type_(kUndefined),
709 vad_activity_(kVadUnknown),
711 interleaved_(true) {}
713 inline void AudioFrame::UpdateFrame(int id, uint32_t timestamp,
715 int samples_per_channel, int sample_rate_hz,
716 SpeechType speech_type,
717 VADActivity vad_activity, int num_channels,
720 timestamp_ = timestamp;
721 samples_per_channel_ = samples_per_channel;
722 sample_rate_hz_ = sample_rate_hz;
723 speech_type_ = speech_type;
724 vad_activity_ = vad_activity;
725 num_channels_ = num_channels;
728 const int length = samples_per_channel * num_channels;
729 assert(length <= kMaxDataSizeSamples && length >= 0);
731 memcpy(data_, data, sizeof(int16_t) * length);
733 memset(data_, 0, sizeof(int16_t) * length);
737 inline void AudioFrame::CopyFrom(const AudioFrame& src) {
738 if (this == &src) return;
741 timestamp_ = src.timestamp_;
742 samples_per_channel_ = src.samples_per_channel_;
743 sample_rate_hz_ = src.sample_rate_hz_;
744 speech_type_ = src.speech_type_;
745 vad_activity_ = src.vad_activity_;
746 num_channels_ = src.num_channels_;
747 energy_ = src.energy_;
748 interleaved_ = src.interleaved_;
750 const int length = samples_per_channel_ * num_channels_;
751 assert(length <= kMaxDataSizeSamples && length >= 0);
752 memcpy(data_, src.data_, sizeof(int16_t) * length);
755 inline void AudioFrame::Mute() {
756 memset(data_, 0, samples_per_channel_ * num_channels_ * sizeof(int16_t));
759 inline AudioFrame& AudioFrame::operator>>=(const int rhs) {
760 assert((num_channels_ > 0) && (num_channels_ < 3));
761 if ((num_channels_ > 2) || (num_channels_ < 1)) return *this;
763 for (int i = 0; i < samples_per_channel_ * num_channels_; i++) {
764 data_[i] = static_cast<int16_t>(data_[i] >> rhs);
769 inline AudioFrame& AudioFrame::Append(const AudioFrame& rhs) {
771 assert((num_channels_ > 0) && (num_channels_ < 3));
772 assert(interleaved_ == rhs.interleaved_);
773 if ((num_channels_ > 2) || (num_channels_ < 1)) return *this;
774 if (num_channels_ != rhs.num_channels_) return *this;
776 if ((vad_activity_ == kVadActive) || rhs.vad_activity_ == kVadActive) {
777 vad_activity_ = kVadActive;
778 } else if (vad_activity_ == kVadUnknown || rhs.vad_activity_ == kVadUnknown) {
779 vad_activity_ = kVadUnknown;
781 if (speech_type_ != rhs.speech_type_) {
782 speech_type_ = kUndefined;
785 int offset = samples_per_channel_ * num_channels_;
786 for (int i = 0; i < rhs.samples_per_channel_ * rhs.num_channels_; i++) {
787 data_[offset + i] = rhs.data_[i];
789 samples_per_channel_ += rhs.samples_per_channel_;
793 inline AudioFrame& AudioFrame::operator+=(const AudioFrame& rhs) {
795 assert((num_channels_ > 0) && (num_channels_ < 3));
796 assert(interleaved_ == rhs.interleaved_);
797 if ((num_channels_ > 2) || (num_channels_ < 1)) return *this;
798 if (num_channels_ != rhs.num_channels_) return *this;
800 bool noPrevData = false;
801 if (samples_per_channel_ != rhs.samples_per_channel_) {
802 if (samples_per_channel_ == 0) {
803 // special case we have no data to start with
804 samples_per_channel_ = rhs.samples_per_channel_;
811 if ((vad_activity_ == kVadActive) || rhs.vad_activity_ == kVadActive) {
812 vad_activity_ = kVadActive;
813 } else if (vad_activity_ == kVadUnknown || rhs.vad_activity_ == kVadUnknown) {
814 vad_activity_ = kVadUnknown;
817 if (speech_type_ != rhs.speech_type_) speech_type_ = kUndefined;
820 memcpy(data_, rhs.data_,
821 sizeof(int16_t) * rhs.samples_per_channel_ * num_channels_);
823 // IMPROVEMENT this can be done very fast in assembly
824 for (int i = 0; i < samples_per_channel_ * num_channels_; i++) {
826 static_cast<int32_t>(data_[i]) + static_cast<int32_t>(rhs.data_[i]);
827 if (wrapGuard < -32768) {
829 } else if (wrapGuard > 32767) {
832 data_[i] = (int16_t)wrapGuard;
836 energy_ = 0xffffffff;
840 inline AudioFrame& AudioFrame::operator-=(const AudioFrame& rhs) {
842 assert((num_channels_ > 0) && (num_channels_ < 3));
843 assert(interleaved_ == rhs.interleaved_);
844 if ((num_channels_ > 2) || (num_channels_ < 1)) return *this;
846 if ((samples_per_channel_ != rhs.samples_per_channel_) ||
847 (num_channels_ != rhs.num_channels_)) {
850 if ((vad_activity_ != kVadPassive) || rhs.vad_activity_ != kVadPassive) {
851 vad_activity_ = kVadUnknown;
853 speech_type_ = kUndefined;
855 for (int i = 0; i < samples_per_channel_ * num_channels_; i++) {
857 static_cast<int32_t>(data_[i]) - static_cast<int32_t>(rhs.data_[i]);
858 if (wrapGuard < -32768) {
860 } else if (wrapGuard > 32767) {
863 data_[i] = (int16_t)wrapGuard;
866 energy_ = 0xffffffff;
870 inline bool IsNewerSequenceNumber(uint16_t sequence_number,
871 uint16_t prev_sequence_number) {
872 return sequence_number != prev_sequence_number &&
873 static_cast<uint16_t>(sequence_number - prev_sequence_number) < 0x8000;
876 inline bool IsNewerTimestamp(uint32_t timestamp, uint32_t prev_timestamp) {
877 return timestamp != prev_timestamp &&
878 static_cast<uint32_t>(timestamp - prev_timestamp) < 0x80000000;
881 inline uint16_t LatestSequenceNumber(uint16_t sequence_number1,
882 uint16_t sequence_number2) {
883 return IsNewerSequenceNumber(sequence_number1, sequence_number2)
888 inline uint32_t LatestTimestamp(uint32_t timestamp1, uint32_t timestamp2) {
889 return IsNewerTimestamp(timestamp1, timestamp2) ? timestamp1 : timestamp2;
892 } // namespace webrtc
894 #endif // MODULE_COMMON_TYPES_H