1ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander/*
2ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander *
4ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander *  Use of this source code is governed by a BSD-style license
5ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander *  that can be found in the LICENSE file in the root of the source
6ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander *  tree. An additional intellectual property rights grant can be found
7ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander *  in the file PATENTS.  All contributing project authors may
8ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander *  be found in the AUTHORS file in the root of the source tree.
9ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander */
10ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
11ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#ifndef WEBRTC_MODULES_INCLUDE_MODULE_COMMON_TYPES_H_
12ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#define WEBRTC_MODULES_INCLUDE_MODULE_COMMON_TYPES_H_
13ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
14ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include <assert.h>
15ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include <string.h>  // memcpy
16ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
17ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include <algorithm>
18ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include <limits>
19ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
20ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/base/constructormagic.h"
21ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/common_types.h"
22ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/common_video/rotation.h"
23ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/typedefs.h"
24ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
25ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellandernamespace webrtc {
26ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
27ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderstruct RTPAudioHeader {
28ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t numEnergy;                  // number of valid entries in arrOfEnergy
29ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t arrOfEnergy[kRtpCsrcSize];  // one energy byte (0-9) per channel
30ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  bool isCNG;                         // is this CNG
316955870806624479723addfae6dcf5d13968796cPeter Kasting  size_t channel;                     // number of channels 2 = stereo
32ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
33ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
34ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderconst int16_t kNoPictureId = -1;
35ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderconst int16_t kMaxOneBytePictureId = 0x7F;    // 7 bits
36ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderconst int16_t kMaxTwoBytePictureId = 0x7FFF;  // 15 bits
37ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderconst int16_t kNoTl0PicIdx = -1;
38ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderconst uint8_t kNoTemporalIdx = 0xFF;
39ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderconst uint8_t kNoSpatialIdx = 0xFF;
40ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderconst uint8_t kNoGofIdx = 0xFF;
41cfc319be1d6afec77bd41eeb70d3e7886dd524dbphilipelconst uint8_t kNumVp9Buffers = 8;
42ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderconst size_t kMaxVp9RefPics = 3;
43ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderconst size_t kMaxVp9FramesInGof = 0xFF;  // 8 bits
44ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderconst size_t kMaxVp9NumberOfSpatialLayers = 8;
45ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderconst int kNoKeyIdx = -1;
46ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
47ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderstruct RTPVideoHeaderVP8 {
48ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  void InitRTPVideoHeaderVP8() {
49ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    nonReference = false;
50ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    pictureId = kNoPictureId;
51ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    tl0PicIdx = kNoTl0PicIdx;
52ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    temporalIdx = kNoTemporalIdx;
53ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    layerSync = false;
54ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    keyIdx = kNoKeyIdx;
55ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    partitionId = 0;
56ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    beginningOfPartition = false;
57ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
58ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
59ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  bool nonReference;          // Frame is discardable.
60ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  int16_t pictureId;          // Picture ID index, 15 bits;
61ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                              // kNoPictureId if PictureID does not exist.
62ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  int16_t tl0PicIdx;          // TL0PIC_IDX, 8 bits;
63ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                              // kNoTl0PicIdx means no value provided.
64ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t temporalIdx;        // Temporal layer index, or kNoTemporalIdx.
65ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  bool layerSync;             // This frame is a layer sync frame.
66ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                              // Disabled if temporalIdx == kNoTemporalIdx.
67ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  int keyIdx;                 // 5 bits; kNoKeyIdx means not used.
68ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  int partitionId;            // VP8 partition ID
69ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  bool beginningOfPartition;  // True if this packet is the first
70ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                              // in a VP8 partition. Otherwise false
71ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
72ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
73ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderenum TemporalStructureMode {
74ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  kTemporalStructureMode1,    // 1 temporal layer structure - i.e., IPPP...
75ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  kTemporalStructureMode2,    // 2 temporal layers 0-1-0-1...
76ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  kTemporalStructureMode3     // 3 temporal layers 0-2-1-2-0-2-1-2...
77ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
78ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
79ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderstruct GofInfoVP9 {
80ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  void SetGofInfoVP9(TemporalStructureMode tm) {
81ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    switch (tm) {
82ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      case kTemporalStructureMode1:
83ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        num_frames_in_gof = 1;
84ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        temporal_idx[0] = 0;
85ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        temporal_up_switch[0] = false;
86ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        num_ref_pics[0] = 1;
87ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        pid_diff[0][0] = 1;
88ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        break;
89ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      case kTemporalStructureMode2:
90ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        num_frames_in_gof = 2;
91ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        temporal_idx[0] = 0;
92ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        temporal_up_switch[0] = false;
93ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        num_ref_pics[0] = 1;
94ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        pid_diff[0][0] = 2;
95ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
96ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        temporal_idx[1] = 1;
97ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        temporal_up_switch[1] = true;
98ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        num_ref_pics[1] = 1;
99ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        pid_diff[1][0] = 1;
100ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        break;
101ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      case kTemporalStructureMode3:
102ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        num_frames_in_gof = 4;
103ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        temporal_idx[0] = 0;
104ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        temporal_up_switch[0] = false;
105ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        num_ref_pics[0] = 1;
106ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        pid_diff[0][0] = 4;
107ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
108ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        temporal_idx[1] = 2;
109ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        temporal_up_switch[1] = true;
110ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        num_ref_pics[1] = 1;
111ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        pid_diff[1][0] = 1;
112ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
113ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        temporal_idx[2] = 1;
114ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        temporal_up_switch[2] = true;
115ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        num_ref_pics[2] = 1;
116ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        pid_diff[2][0] = 2;
117ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
118ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        temporal_idx[3] = 2;
119ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        temporal_up_switch[3] = false;
120ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        num_ref_pics[3] = 2;
121ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        pid_diff[3][0] = 1;
122ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        pid_diff[3][1] = 2;
123ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        break;
124ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      default:
125ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        assert(false);
126ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    }
127ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
128ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
129ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  void CopyGofInfoVP9(const GofInfoVP9& src) {
130ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    num_frames_in_gof = src.num_frames_in_gof;
131ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    for (size_t i = 0; i < num_frames_in_gof; ++i) {
132ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      temporal_idx[i] = src.temporal_idx[i];
133ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      temporal_up_switch[i] = src.temporal_up_switch[i];
134ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      num_ref_pics[i] = src.num_ref_pics[i];
135c253a1c00eefd966aa59e00885fae4714806094fasapersson      for (uint8_t r = 0; r < num_ref_pics[i]; ++r) {
136ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        pid_diff[i][r] = src.pid_diff[i][r];
137ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      }
138ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    }
139ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
140ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
141ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  size_t num_frames_in_gof;
142ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t temporal_idx[kMaxVp9FramesInGof];
143ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  bool temporal_up_switch[kMaxVp9FramesInGof];
144c253a1c00eefd966aa59e00885fae4714806094fasapersson  uint8_t num_ref_pics[kMaxVp9FramesInGof];
145c253a1c00eefd966aa59e00885fae4714806094fasapersson  uint8_t pid_diff[kMaxVp9FramesInGof][kMaxVp9RefPics];
146ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
147ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
148ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderstruct RTPVideoHeaderVP9 {
149ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  void InitRTPVideoHeaderVP9() {
150ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    inter_pic_predicted = false;
151ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    flexible_mode = false;
152ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    beginning_of_frame = false;
153ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    end_of_frame = false;
154ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    ss_data_available = false;
155ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    picture_id = kNoPictureId;
156ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    max_picture_id = kMaxTwoBytePictureId;
157ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    tl0_pic_idx = kNoTl0PicIdx;
158ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    temporal_idx = kNoTemporalIdx;
159ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    spatial_idx = kNoSpatialIdx;
160ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    temporal_up_switch = false;
161ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    inter_layer_predicted = false;
162ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    gof_idx = kNoGofIdx;
163ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    num_ref_pics = 0;
164ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    num_spatial_layers = 1;
165ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
166ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
167ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  bool inter_pic_predicted;  // This layer frame is dependent on previously
168ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                             // coded frame(s).
169ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  bool flexible_mode;        // This frame is in flexible mode.
170ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  bool beginning_of_frame;   // True if this packet is the first in a VP9 layer
171ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                             // frame.
172ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  bool end_of_frame;  // True if this packet is the last in a VP9 layer frame.
173ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  bool ss_data_available;  // True if SS data is available in this payload
174ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                           // descriptor.
175ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  int16_t picture_id;      // PictureID index, 15 bits;
176ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                           // kNoPictureId if PictureID does not exist.
177ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  int16_t max_picture_id;  // Maximum picture ID index; either 0x7F or 0x7FFF;
178ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  int16_t tl0_pic_idx;     // TL0PIC_IDX, 8 bits;
179ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                           // kNoTl0PicIdx means no value provided.
180ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t temporal_idx;    // Temporal layer index, or kNoTemporalIdx.
181ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t spatial_idx;     // Spatial layer index, or kNoSpatialIdx.
182ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  bool temporal_up_switch;  // True if upswitch to higher frame rate is possible
183ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                            // starting from this frame.
184ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  bool inter_layer_predicted;  // Frame is dependent on directly lower spatial
185ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                               // layer frame.
186ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
187ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t gof_idx;  // Index to predefined temporal frame info in SS data.
188ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
189c253a1c00eefd966aa59e00885fae4714806094fasapersson  uint8_t num_ref_pics;  // Number of reference pictures used by this layer
190c253a1c00eefd966aa59e00885fae4714806094fasapersson                         // frame.
191c253a1c00eefd966aa59e00885fae4714806094fasapersson  uint8_t pid_diff[kMaxVp9RefPics];  // P_DIFF signaled to derive the PictureID
192ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                                     // of the reference pictures.
193ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  int16_t ref_picture_id[kMaxVp9RefPics];  // PictureID of reference pictures.
194ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
195ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // SS data.
196ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  size_t num_spatial_layers;  // Always populated.
197ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  bool spatial_layer_resolution_present;
198ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint16_t width[kMaxVp9NumberOfSpatialLayers];
199ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint16_t height[kMaxVp9NumberOfSpatialLayers];
200ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  GofInfoVP9 gof;
201ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
202ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
203ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander// The packetization types that we support: single, aggregated, and fragmented.
204ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderenum H264PacketizationTypes {
205ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  kH264SingleNalu,  // This packet contains a single NAL unit.
206ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  kH264StapA,       // This packet contains STAP-A (single time
207ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                    // aggregation) packets. If this packet has an
208ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                    // associated NAL unit type, it'll be for the
209ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                    // first such aggregated packet.
210ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  kH264FuA,         // This packet contains a FU-A (fragmentation
211ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                    // unit) packet, meaning it is a part of a frame
212ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                    // that was too large to fit into a single packet.
213ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
214ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
215ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderstruct RTPVideoHeaderH264 {
216ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t nalu_type;  // The NAL unit type. If this is a header for a
217ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                      // fragmented packet, it's the NAL unit type of
218ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                      // the original data. If this is the header for an
219ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                      // aggregated packet, it's the NAL unit type of
220ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                      // the first NAL unit in the packet.
221ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  H264PacketizationTypes packetization_type;
222ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
223ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
224ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderunion RTPVideoTypeHeader {
225ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  RTPVideoHeaderVP8 VP8;
226ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  RTPVideoHeaderVP9 VP9;
227ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  RTPVideoHeaderH264 H264;
228ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
229ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
230ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderenum RtpVideoCodecTypes {
231ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  kRtpVideoNone,
232ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  kRtpVideoGeneric,
233ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  kRtpVideoVp8,
234ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  kRtpVideoVp9,
235ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  kRtpVideoH264
236ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
237ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander// Since RTPVideoHeader is used as a member of a union, it can't have a
238ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander// non-trivial default constructor.
239ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderstruct RTPVideoHeader {
240ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint16_t width;  // size
241ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint16_t height;
242ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  VideoRotation rotation;
243ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
244ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  bool isFirstPacket;    // first packet in frame
245ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t simulcastIdx;  // Index if the simulcast encoder creating
246ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                         // this frame, 0 if not using simulcast.
247ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  RtpVideoCodecTypes codec;
248ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  RTPVideoTypeHeader codecHeader;
249ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
250ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderunion RTPTypeHeader {
251ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  RTPAudioHeader Audio;
252ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  RTPVideoHeader Video;
253ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
254ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
255ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderstruct WebRtcRTPHeader {
256ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  RTPHeader header;
257ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  FrameType frameType;
258ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  RTPTypeHeader type;
259ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // NTP time of the capture time in local timebase in milliseconds.
260ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  int64_t ntp_time_ms;
261ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
262ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
263ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderclass RTPFragmentationHeader {
264ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander public:
265ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  RTPFragmentationHeader()
266ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      : fragmentationVectorSize(0),
267ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        fragmentationOffset(NULL),
268ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        fragmentationLength(NULL),
269ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        fragmentationTimeDiff(NULL),
270ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        fragmentationPlType(NULL) {};
271ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
272ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  ~RTPFragmentationHeader() {
273ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    delete[] fragmentationOffset;
274ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    delete[] fragmentationLength;
275ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    delete[] fragmentationTimeDiff;
276ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    delete[] fragmentationPlType;
277ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
278ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
279ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  void CopyFrom(const RTPFragmentationHeader& src) {
280ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    if (this == &src) {
281ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      return;
282ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    }
283ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
284ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    if (src.fragmentationVectorSize != fragmentationVectorSize) {
285ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      // new size of vectors
286ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
287ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      // delete old
288ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      delete[] fragmentationOffset;
289ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      fragmentationOffset = NULL;
290ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      delete[] fragmentationLength;
291ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      fragmentationLength = NULL;
292ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      delete[] fragmentationTimeDiff;
293ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      fragmentationTimeDiff = NULL;
294ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      delete[] fragmentationPlType;
295ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      fragmentationPlType = NULL;
296ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
297ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      if (src.fragmentationVectorSize > 0) {
298ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        // allocate new
299ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        if (src.fragmentationOffset) {
300ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander          fragmentationOffset = new size_t[src.fragmentationVectorSize];
301ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        }
302ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        if (src.fragmentationLength) {
303ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander          fragmentationLength = new size_t[src.fragmentationVectorSize];
304ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        }
305ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        if (src.fragmentationTimeDiff) {
306ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander          fragmentationTimeDiff = new uint16_t[src.fragmentationVectorSize];
307ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        }
308ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        if (src.fragmentationPlType) {
309ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander          fragmentationPlType = new uint8_t[src.fragmentationVectorSize];
310ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        }
311ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      }
312ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      // set new size
313ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      fragmentationVectorSize = src.fragmentationVectorSize;
314ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    }
315ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
316ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    if (src.fragmentationVectorSize > 0) {
317ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      // copy values
318ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      if (src.fragmentationOffset) {
319ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        memcpy(fragmentationOffset, src.fragmentationOffset,
320ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander               src.fragmentationVectorSize * sizeof(size_t));
321ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      }
322ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      if (src.fragmentationLength) {
323ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        memcpy(fragmentationLength, src.fragmentationLength,
324ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander               src.fragmentationVectorSize * sizeof(size_t));
325ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      }
326ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      if (src.fragmentationTimeDiff) {
327ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        memcpy(fragmentationTimeDiff, src.fragmentationTimeDiff,
328ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander               src.fragmentationVectorSize * sizeof(uint16_t));
329ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      }
330ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      if (src.fragmentationPlType) {
331ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        memcpy(fragmentationPlType, src.fragmentationPlType,
332ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander               src.fragmentationVectorSize * sizeof(uint8_t));
333ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      }
334ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    }
335ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
336ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
337ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  void VerifyAndAllocateFragmentationHeader(const size_t size) {
338ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    assert(size <= std::numeric_limits<uint16_t>::max());
339ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    const uint16_t size16 = static_cast<uint16_t>(size);
340ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    if (fragmentationVectorSize < size16) {
341ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      uint16_t oldVectorSize = fragmentationVectorSize;
342ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      {
343ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        // offset
344ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        size_t* oldOffsets = fragmentationOffset;
345ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        fragmentationOffset = new size_t[size16];
346ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        memset(fragmentationOffset + oldVectorSize, 0,
347ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander               sizeof(size_t) * (size16 - oldVectorSize));
348ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        // copy old values
349ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        memcpy(fragmentationOffset, oldOffsets,
350ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander               sizeof(size_t) * oldVectorSize);
351ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        delete[] oldOffsets;
352ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      }
353ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      // length
354ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      {
355ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        size_t* oldLengths = fragmentationLength;
356ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        fragmentationLength = new size_t[size16];
357ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        memset(fragmentationLength + oldVectorSize, 0,
358ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander               sizeof(size_t) * (size16 - oldVectorSize));
359ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        memcpy(fragmentationLength, oldLengths,
360ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander               sizeof(size_t) * oldVectorSize);
361ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        delete[] oldLengths;
362ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      }
363ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      // time diff
364ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      {
365ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        uint16_t* oldTimeDiffs = fragmentationTimeDiff;
366ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        fragmentationTimeDiff = new uint16_t[size16];
367ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        memset(fragmentationTimeDiff + oldVectorSize, 0,
368ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander               sizeof(uint16_t) * (size16 - oldVectorSize));
369ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        memcpy(fragmentationTimeDiff, oldTimeDiffs,
370ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander               sizeof(uint16_t) * oldVectorSize);
371ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        delete[] oldTimeDiffs;
372ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      }
373ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      // payload type
374ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      {
375ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        uint8_t* oldTimePlTypes = fragmentationPlType;
376ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        fragmentationPlType = new uint8_t[size16];
377ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        memset(fragmentationPlType + oldVectorSize, 0,
378ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander               sizeof(uint8_t) * (size16 - oldVectorSize));
379ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        memcpy(fragmentationPlType, oldTimePlTypes,
380ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander               sizeof(uint8_t) * oldVectorSize);
381ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        delete[] oldTimePlTypes;
382ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      }
383ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      fragmentationVectorSize = size16;
384ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    }
385ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
386ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
387ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint16_t fragmentationVectorSize;  // Number of fragmentations
388ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  size_t* fragmentationOffset;       // Offset of pointer to data for each
389ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                                     // fragmentation
390ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  size_t* fragmentationLength;       // Data size for each fragmentation
391ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint16_t* fragmentationTimeDiff;   // Timestamp difference relative "now" for
392ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                                     // each fragmentation
393ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t* fragmentationPlType;      // Payload type of each fragmentation
394ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
395ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander private:
396ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  RTC_DISALLOW_COPY_AND_ASSIGN(RTPFragmentationHeader);
397ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
398ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
399ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderstruct RTCPVoIPMetric {
400ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // RFC 3611 4.7
401ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t lossRate;
402ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t discardRate;
403ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t burstDensity;
404ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t gapDensity;
405ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint16_t burstDuration;
406ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint16_t gapDuration;
407ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint16_t roundTripDelay;
408ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint16_t endSystemDelay;
409ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t signalLevel;
410ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t noiseLevel;
411ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t RERL;
412ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t Gmin;
413ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t Rfactor;
414ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t extRfactor;
415ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t MOSLQ;
416ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t MOSCQ;
417ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint8_t RXconfig;
418ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint16_t JBnominal;
419ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint16_t JBmax;
420ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint16_t JBabsMax;
421ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
422ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
423ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander// Types for the FEC packet masks. The type |kFecMaskRandom| is based on a
424ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander// random loss model. The type |kFecMaskBursty| is based on a bursty/consecutive
425ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander// loss model. The packet masks are defined in
426ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander// modules/rtp_rtcp/fec_private_tables_random(bursty).h
427ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderenum FecMaskType {
428ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  kFecMaskRandom,
429ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  kFecMaskBursty,
430ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
431ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
432ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander// Struct containing forward error correction settings.
433ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderstruct FecProtectionParams {
434ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  int fec_rate;
435ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  bool use_uep_protection;
436ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  int max_fec_frames;
437ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  FecMaskType fec_mask_type;
438ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
439ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
440ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander// Interface used by the CallStats class to distribute call statistics.
441ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander// Callbacks will be triggered as soon as the class has been registered to a
442ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander// CallStats object using RegisterStatsObserver.
443ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderclass CallStatsObserver {
444ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander public:
445ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  virtual void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) = 0;
446ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
447ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  virtual ~CallStatsObserver() {}
448ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
449ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
450ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderstruct VideoContentMetrics {
451ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  VideoContentMetrics()
452ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      : motion_magnitude(0.0f),
453ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        spatial_pred_err(0.0f),
454ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        spatial_pred_err_h(0.0f),
455ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        spatial_pred_err_v(0.0f) {}
456ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
457ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  void Reset() {
458ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    motion_magnitude = 0.0f;
459ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    spatial_pred_err = 0.0f;
460ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    spatial_pred_err_h = 0.0f;
461ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    spatial_pred_err_v = 0.0f;
462ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
463ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  float motion_magnitude;
464ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  float spatial_pred_err;
465ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  float spatial_pred_err_h;
466ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  float spatial_pred_err_v;
467ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
468ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
469ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander/* This class holds up to 60 ms of super-wideband (32 kHz) stereo audio. It
470ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander * allows for adding and subtracting frames while keeping track of the resulting
471ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander * states.
472ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander *
473ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander * Notes
474ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander * - The total number of samples in |data_| is
475ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander *   samples_per_channel_ * num_channels_
476ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander *
477ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander * - Stereo data is interleaved starting with the left channel.
478ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander *
479ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander * - The +operator assume that you would never add exactly opposite frames when
480ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander *   deciding the resulting state. To do this use the -operator.
481ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander */
482ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderclass AudioFrame {
483ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander public:
484ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // Stereo, 32 kHz, 60 ms (2 * 32 * 60)
485ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  static const size_t kMaxDataSizeSamples = 3840;
486ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
487ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  enum VADActivity {
488ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    kVadActive = 0,
489ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    kVadPassive = 1,
490ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    kVadUnknown = 2
491ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  };
492ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  enum SpeechType {
493ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    kNormalSpeech = 0,
494ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    kPLC = 1,
495ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    kCNG = 2,
496ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    kPLCCNG = 3,
497ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    kUndefined = 4
498ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  };
499ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
500ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  AudioFrame();
501ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  virtual ~AudioFrame() {}
502ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
503ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // Resets all members to their default state (except does not modify the
504ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // contents of |data_|).
505ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  void Reset();
506ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
507ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // |interleaved_| is not changed by this method.
508ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  void UpdateFrame(int id, uint32_t timestamp, const int16_t* data,
509ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                   size_t samples_per_channel, int sample_rate_hz,
510ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                   SpeechType speech_type, VADActivity vad_activity,
5116955870806624479723addfae6dcf5d13968796cPeter Kasting                   size_t num_channels = 1, uint32_t energy = -1);
512ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
513ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  AudioFrame& Append(const AudioFrame& rhs);
514ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
515ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  void CopyFrom(const AudioFrame& src);
516ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
517ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  void Mute();
518ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
519ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  AudioFrame& operator>>=(const int rhs);
520ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  AudioFrame& operator+=(const AudioFrame& rhs);
521ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  AudioFrame& operator-=(const AudioFrame& rhs);
522ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
523ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  int id_;
524ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // RTP timestamp of the first sample in the AudioFrame.
525ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint32_t timestamp_;
526ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // Time since the first frame in milliseconds.
527ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // -1 represents an uninitialized value.
528ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  int64_t elapsed_time_ms_;
529ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // NTP time of the estimated capture time in local timebase in milliseconds.
530ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // -1 represents an uninitialized value.
531ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  int64_t ntp_time_ms_;
532ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  int16_t data_[kMaxDataSizeSamples];
533ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  size_t samples_per_channel_;
534ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  int sample_rate_hz_;
5356955870806624479723addfae6dcf5d13968796cPeter Kasting  size_t num_channels_;
536ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  SpeechType speech_type_;
537ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  VADActivity vad_activity_;
538ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // Note that there is no guarantee that |energy_| is correct. Any user of this
539ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // member must verify that the value is correct.
540ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // TODO(henrike) Remove |energy_|.
541ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // See https://code.google.com/p/webrtc/issues/detail?id=3315.
542ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  uint32_t energy_;
543ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  bool interleaved_;
544ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
545ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander private:
546ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  RTC_DISALLOW_COPY_AND_ASSIGN(AudioFrame);
547ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
548ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
549ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderinline AudioFrame::AudioFrame()
550ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    : data_() {
551ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  Reset();
552ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander}
553ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
554ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderinline void AudioFrame::Reset() {
555ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  id_ = -1;
556ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // TODO(wu): Zero is a valid value for |timestamp_|. We should initialize
557ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // to an invalid value, or add a new member to indicate invalidity.
558ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  timestamp_ = 0;
559ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  elapsed_time_ms_ = -1;
560ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  ntp_time_ms_ = -1;
561ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  samples_per_channel_ = 0;
562ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  sample_rate_hz_ = 0;
563ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  num_channels_ = 0;
564ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  speech_type_ = kUndefined;
565ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  vad_activity_ = kVadUnknown;
566ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  energy_ = 0xffffffff;
567ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  interleaved_ = true;
568ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander}
569ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
570ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderinline void AudioFrame::UpdateFrame(int id,
571ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                                    uint32_t timestamp,
572ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                                    const int16_t* data,
573ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                                    size_t samples_per_channel,
574ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                                    int sample_rate_hz,
575ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                                    SpeechType speech_type,
576ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                                    VADActivity vad_activity,
5776955870806624479723addfae6dcf5d13968796cPeter Kasting                                    size_t num_channels,
578ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                                    uint32_t energy) {
579ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  id_ = id;
580ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  timestamp_ = timestamp;
581ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  samples_per_channel_ = samples_per_channel;
582ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  sample_rate_hz_ = sample_rate_hz;
583ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  speech_type_ = speech_type;
584ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  vad_activity_ = vad_activity;
585ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  num_channels_ = num_channels;
586ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  energy_ = energy;
587ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
588ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  const size_t length = samples_per_channel * num_channels;
589ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  assert(length <= kMaxDataSizeSamples);
590ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  if (data != NULL) {
591ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    memcpy(data_, data, sizeof(int16_t) * length);
592ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  } else {
593ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    memset(data_, 0, sizeof(int16_t) * length);
594ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
595ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander}
596ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
597ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderinline void AudioFrame::CopyFrom(const AudioFrame& src) {
598ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  if (this == &src) return;
599ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
600ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  id_ = src.id_;
601ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  timestamp_ = src.timestamp_;
602ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  elapsed_time_ms_ = src.elapsed_time_ms_;
603ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  ntp_time_ms_ = src.ntp_time_ms_;
604ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  samples_per_channel_ = src.samples_per_channel_;
605ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  sample_rate_hz_ = src.sample_rate_hz_;
606ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  speech_type_ = src.speech_type_;
607ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  vad_activity_ = src.vad_activity_;
608ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  num_channels_ = src.num_channels_;
609ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  energy_ = src.energy_;
610ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  interleaved_ = src.interleaved_;
611ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
612ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  const size_t length = samples_per_channel_ * num_channels_;
613ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  assert(length <= kMaxDataSizeSamples);
614ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  memcpy(data_, src.data_, sizeof(int16_t) * length);
615ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander}
616ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
617ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderinline void AudioFrame::Mute() {
618ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  memset(data_, 0, samples_per_channel_ * num_channels_ * sizeof(int16_t));
619ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander}
620ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
621ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderinline AudioFrame& AudioFrame::operator>>=(const int rhs) {
622ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  assert((num_channels_ > 0) && (num_channels_ < 3));
623ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  if ((num_channels_ > 2) || (num_channels_ < 1)) return *this;
624ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
625ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  for (size_t i = 0; i < samples_per_channel_ * num_channels_; i++) {
626ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    data_[i] = static_cast<int16_t>(data_[i] >> rhs);
627ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
628ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  return *this;
629ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander}
630ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
631ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderinline AudioFrame& AudioFrame::Append(const AudioFrame& rhs) {
632ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // Sanity check
633ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  assert((num_channels_ > 0) && (num_channels_ < 3));
634ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  assert(interleaved_ == rhs.interleaved_);
635ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  if ((num_channels_ > 2) || (num_channels_ < 1)) return *this;
636ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  if (num_channels_ != rhs.num_channels_) return *this;
637ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
638ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  if ((vad_activity_ == kVadActive) || rhs.vad_activity_ == kVadActive) {
639ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    vad_activity_ = kVadActive;
640ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  } else if (vad_activity_ == kVadUnknown || rhs.vad_activity_ == kVadUnknown) {
641ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    vad_activity_ = kVadUnknown;
642ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
643ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  if (speech_type_ != rhs.speech_type_) {
644ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    speech_type_ = kUndefined;
645ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
646ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
647ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  size_t offset = samples_per_channel_ * num_channels_;
648ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  for (size_t i = 0; i < rhs.samples_per_channel_ * rhs.num_channels_; i++) {
649ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    data_[offset + i] = rhs.data_[i];
650ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
651ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  samples_per_channel_ += rhs.samples_per_channel_;
652ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  return *this;
653ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander}
654ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
655ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellandernamespace {
656ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderinline int16_t ClampToInt16(int32_t input) {
657ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  if (input < -0x00008000) {
658ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    return -0x8000;
659ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  } else if (input > 0x00007FFF) {
660ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    return 0x7FFF;
661ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  } else {
662ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    return static_cast<int16_t>(input);
663ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
664ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander}
665ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander}
666ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
667ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderinline AudioFrame& AudioFrame::operator+=(const AudioFrame& rhs) {
668ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // Sanity check
669ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  assert((num_channels_ > 0) && (num_channels_ < 3));
670ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  assert(interleaved_ == rhs.interleaved_);
671ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  if ((num_channels_ > 2) || (num_channels_ < 1)) return *this;
672ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  if (num_channels_ != rhs.num_channels_) return *this;
673ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
674ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  bool noPrevData = false;
675ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  if (samples_per_channel_ != rhs.samples_per_channel_) {
676ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    if (samples_per_channel_ == 0) {
677ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      // special case we have no data to start with
678ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      samples_per_channel_ = rhs.samples_per_channel_;
679ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      noPrevData = true;
680ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    } else {
681ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      return *this;
682ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    }
683ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
684ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
685ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  if ((vad_activity_ == kVadActive) || rhs.vad_activity_ == kVadActive) {
686ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    vad_activity_ = kVadActive;
687ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  } else if (vad_activity_ == kVadUnknown || rhs.vad_activity_ == kVadUnknown) {
688ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    vad_activity_ = kVadUnknown;
689ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
690ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
691ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  if (speech_type_ != rhs.speech_type_) speech_type_ = kUndefined;
692ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
693ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  if (noPrevData) {
694ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    memcpy(data_, rhs.data_,
695ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander           sizeof(int16_t) * rhs.samples_per_channel_ * num_channels_);
696ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  } else {
697ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    // IMPROVEMENT this can be done very fast in assembly
698ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    for (size_t i = 0; i < samples_per_channel_ * num_channels_; i++) {
699ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      int32_t wrap_guard =
700ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander          static_cast<int32_t>(data_[i]) + static_cast<int32_t>(rhs.data_[i]);
701ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      data_[i] = ClampToInt16(wrap_guard);
702ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    }
703ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
704ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  energy_ = 0xffffffff;
705ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  return *this;
706ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander}
707ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
708ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderinline AudioFrame& AudioFrame::operator-=(const AudioFrame& rhs) {
709ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // Sanity check
710ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  assert((num_channels_ > 0) && (num_channels_ < 3));
711ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  assert(interleaved_ == rhs.interleaved_);
712ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  if ((num_channels_ > 2) || (num_channels_ < 1)) return *this;
713ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
714ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  if ((samples_per_channel_ != rhs.samples_per_channel_) ||
715ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      (num_channels_ != rhs.num_channels_)) {
716ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    return *this;
717ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
718ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  if ((vad_activity_ != kVadPassive) || rhs.vad_activity_ != kVadPassive) {
719ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    vad_activity_ = kVadUnknown;
720ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
721ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  speech_type_ = kUndefined;
722ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
723ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  for (size_t i = 0; i < samples_per_channel_ * num_channels_; i++) {
724ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    int32_t wrap_guard =
725ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        static_cast<int32_t>(data_[i]) - static_cast<int32_t>(rhs.data_[i]);
726ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    data_[i] = ClampToInt16(wrap_guard);
727ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
728ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  energy_ = 0xffffffff;
729ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  return *this;
730ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander}
731ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
732ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderinline bool IsNewerSequenceNumber(uint16_t sequence_number,
733ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                                  uint16_t prev_sequence_number) {
734ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // Distinguish between elements that are exactly 0x8000 apart.
735ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // If s1>s2 and |s1-s2| = 0x8000: IsNewer(s1,s2)=true, IsNewer(s2,s1)=false
736ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // rather than having IsNewer(s1,s2) = IsNewer(s2,s1) = false.
737ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  if (static_cast<uint16_t>(sequence_number - prev_sequence_number) == 0x8000) {
738ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    return sequence_number > prev_sequence_number;
739ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
740ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  return sequence_number != prev_sequence_number &&
741ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander         static_cast<uint16_t>(sequence_number - prev_sequence_number) < 0x8000;
742ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander}
743ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
744ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderinline bool IsNewerTimestamp(uint32_t timestamp, uint32_t prev_timestamp) {
745ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // Distinguish between elements that are exactly 0x80000000 apart.
746ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // If t1>t2 and |t1-t2| = 0x80000000: IsNewer(t1,t2)=true,
747ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // IsNewer(t2,t1)=false
748ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // rather than having IsNewer(t1,t2) = IsNewer(t2,t1) = false.
749ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  if (static_cast<uint32_t>(timestamp - prev_timestamp) == 0x80000000) {
750ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    return timestamp > prev_timestamp;
751ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
752ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  return timestamp != prev_timestamp &&
753ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander         static_cast<uint32_t>(timestamp - prev_timestamp) < 0x80000000;
754ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander}
755ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
756ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderinline uint16_t LatestSequenceNumber(uint16_t sequence_number1,
757ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander                                     uint16_t sequence_number2) {
758ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  return IsNewerSequenceNumber(sequence_number1, sequence_number2)
759ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander             ? sequence_number1
760ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander             : sequence_number2;
761ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander}
762ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
763ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderinline uint32_t LatestTimestamp(uint32_t timestamp1, uint32_t timestamp2) {
764ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  return IsNewerTimestamp(timestamp1, timestamp2) ? timestamp1 : timestamp2;
765ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander}
766ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
767ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander// Utility class to unwrap a sequence number to a larger type, for easier
768ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander// handling large ranges. Note that sequence numbers will never be unwrapped
769ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander// to a negative value.
770ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellanderclass SequenceNumberUnwrapper {
771ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander public:
772ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  SequenceNumberUnwrapper() : last_seq_(-1) {}
773ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
774ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // Get the unwrapped sequence, but don't update the internal state.
775ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  int64_t UnwrapWithoutUpdate(uint16_t sequence_number) {
776ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    if (last_seq_ == -1)
777ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      return sequence_number;
778ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
779ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    uint16_t cropped_last = static_cast<uint16_t>(last_seq_);
780ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    int64_t delta = sequence_number - cropped_last;
781ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    if (IsNewerSequenceNumber(sequence_number, cropped_last)) {
782ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      if (delta < 0)
783ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander        delta += (1 << 16);  // Wrap forwards.
784ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    } else if (delta > 0 && (last_seq_ + delta - (1 << 16)) >= 0) {
785ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      // If sequence_number is older but delta is positive, this is a backwards
786ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      // wrap-around. However, don't wrap backwards past 0 (unwrapped).
787ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander      delta -= (1 << 16);
788ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    }
789ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
790ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    return last_seq_ + delta;
791ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
792ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
793ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // Only update the internal state to the specified last (unwrapped) sequence.
794ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  void UpdateLast(int64_t last_sequence) { last_seq_ = last_sequence; }
795ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
796ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  // Unwrap the sequence number and update the internal state.
797ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  int64_t Unwrap(uint16_t sequence_number) {
798ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    int64_t unwrapped = UnwrapWithoutUpdate(sequence_number);
799ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    UpdateLast(unwrapped);
800ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander    return unwrapped;
801ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  }
802ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
803ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander private:
804ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander  int64_t last_seq_;
805ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander};
806ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
807ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander}  // namespace webrtc
808ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander
809ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#endif  // WEBRTC_MODULES_INCLUDE_MODULE_COMMON_TYPES_H_
810