summaryrefslogtreecommitdiffstats
path: root/chromium/media/cast/rtcp/rtcp_utility.h
blob: 34f3f25a889e4f5d6eefc55ad52508d5c89277f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MEDIA_CAST_RTCP_RTCP_UTILITY_H_
#define MEDIA_CAST_RTCP_RTCP_UTILITY_H_

#include "media/cast/cast_config.h"
#include "media/cast/cast_defines.h"
#include "media/cast/logging/logging_defines.h"
#include "media/cast/rtcp/rtcp_defines.h"

namespace media {
namespace cast {

static const int kRtcpRpsiDataSize = 30;

// RFC 3550 page 44, including end null.
static const size_t kRtcpCnameSize = 256;
static const int kRtcpMaxNumberOfRembFeedbackSsrcs = 255;

static const uint32 kRemb = ('R' << 24) + ('E' << 16) + ('M' << 8) + 'B';
static const uint32 kCast = ('C' << 24) + ('A' << 16) + ('S' << 8) + 'T';

static const uint8 kReceiverLogSubtype = 2;

static const size_t kRtcpMaxReceiverLogMessages = 256;
static const size_t kRtcpMaxNackFields = 253;
static const size_t kRtcpMaxCastLossFields = 100;

struct RtcpFieldReceiverReport {
  // RFC 3550.
  uint32 sender_ssrc;
  uint8 number_of_report_blocks;
};

struct RtcpFieldSenderReport {
  // RFC 3550.
  uint32 sender_ssrc;
  uint8 number_of_report_blocks;
  uint32 ntp_most_significant;
  uint32 ntp_least_significant;
  uint32 rtp_timestamp;
  uint32 sender_packet_count;
  uint32 sender_octet_count;
};

struct RtcpFieldReportBlockItem {
  // RFC 3550.
  uint32 ssrc;
  uint8 fraction_lost;
  uint32 cumulative_number_of_packets_lost;
  uint32 extended_highest_sequence_number;
  uint32 jitter;
  uint32 last_sender_report;
  uint32 delay_last_sender_report;
};

struct RtcpFieldSdesCName {
  // RFC 3550
  uint32 sender_ssrc;
  char name[kRtcpCnameSize];
};

struct RtcpFieldBye {
  // RFC 3550.
  uint32 sender_ssrc;
};

struct RtcpFieldGenericRtpFeedbackNack {
  // RFC 4585.
  uint32 sender_ssrc;
  uint32 media_ssrc;
};

struct RtcpFieldGenericRtpFeedbackNackItem {
  // RFC 4585.
  uint16 packet_id;
  uint16 bitmask;
};

struct RtcpFieldPayloadSpecificFir {
  // RFC 5104.
  uint32 sender_ssrc;
  uint32 media_ssrc;  // zero!
};

struct RtcpFieldPayloadSpecificFirItem {
  // RFC 5104.
  uint32 ssrc;
  uint8 command_sequence_number;
};

struct RtcpFieldPayloadSpecificPli {
  // RFC 4585.
  uint32 sender_ssrc;
  uint32 media_ssrc;
};

struct RtcpFieldPayloadSpecificRpsi {
  // RFC 4585.
  uint32 sender_ssrc;
  uint32 media_ssrc;
  uint8 payload_type;
  uint16 number_of_valid_bits;
  uint8 native_bit_string[kRtcpRpsiDataSize];
};

struct RtcpFieldXr {
  // RFC 3611.
  uint32 sender_ssrc;
};

struct RtcpFieldXrRrtr {
  // RFC 3611.
  uint32 ntp_most_significant;
  uint32 ntp_least_significant;
};

struct RtcpFieldXrDlrr {
  // RFC 3611.
  uint32 receivers_ssrc;
  uint32 last_receiver_report;
  uint32 delay_last_receiver_report;
};

struct RtcpFieldPayloadSpecificApplication {
  uint32 sender_ssrc;
  uint32 media_ssrc;
};

struct RtcpFieldPayloadSpecificRembItem {
  uint32 bitrate;
  uint8 number_of_ssrcs;
  uint32 ssrcs[kRtcpMaxNumberOfRembFeedbackSsrcs];
};

struct RtcpFieldPayloadSpecificCastItem {
  uint8 last_frame_id;
  uint8 number_of_lost_fields;
  uint16 target_delay_ms;
};

struct RtcpFieldPayloadSpecificCastNackItem {
  uint8 frame_id;
  uint16 packet_id;
  uint8 bitmask;
};

struct RtcpFieldApplicationSpecificCastReceiverLogItem {
  uint32 sender_ssrc;
  uint32 rtp_timestamp;
  uint32 event_timestamp_base;
  uint8 event;
  union {
    uint16 packet_id;
    int16 delay_delta;
  } delay_delta_or_packet_id;
  uint16 event_timestamp_delta;
};

union RtcpField {
  RtcpFieldReceiverReport receiver_report;
  RtcpFieldSenderReport sender_report;
  RtcpFieldReportBlockItem report_block_item;
  RtcpFieldSdesCName c_name;
  RtcpFieldBye bye;

  RtcpFieldXr extended_report;
  RtcpFieldXrRrtr rrtr;
  RtcpFieldXrDlrr dlrr;

  RtcpFieldGenericRtpFeedbackNack nack;
  RtcpFieldGenericRtpFeedbackNackItem nack_item;

  RtcpFieldPayloadSpecificPli pli;
  RtcpFieldPayloadSpecificRpsi rpsi;
  RtcpFieldPayloadSpecificFir fir;
  RtcpFieldPayloadSpecificFirItem fir_item;
  RtcpFieldPayloadSpecificApplication application_specific;
  RtcpFieldPayloadSpecificRembItem remb_item;
  RtcpFieldPayloadSpecificCastItem cast_item;
  RtcpFieldPayloadSpecificCastNackItem cast_nack_item;

  RtcpFieldApplicationSpecificCastReceiverLogItem cast_receiver_log;
};

enum RtcpFieldTypes {
  kRtcpNotValidCode,

  // RFC 3550.
  kRtcpRrCode,
  kRtcpSrCode,
  kRtcpReportBlockItemCode,
  kRtcpSdesCode,
  kRtcpSdesChunkCode,
  kRtcpByeCode,

  // RFC 3611.
  kRtcpXrCode,
  kRtcpXrRrtrCode,
  kRtcpXrDlrrCode,
  kRtcpXrUnknownItemCode,

  // RFC 4585.
  kRtcpGenericRtpFeedbackNackCode,
  kRtcpGenericRtpFeedbackNackItemCode,
  kRtcpPayloadSpecificPliCode,
  kRtcpPayloadSpecificRpsiCode,
  kRtcpPayloadSpecificAppCode,

  // Application specific.
  kRtcpPayloadSpecificRembCode,
  kRtcpPayloadSpecificRembItemCode,
  kRtcpPayloadSpecificCastCode,
  kRtcpPayloadSpecificCastNackItemCode,
  kRtcpApplicationSpecificCastReceiverLogCode,
  kRtcpApplicationSpecificCastReceiverLogFrameCode,
  kRtcpApplicationSpecificCastReceiverLogEventCode,

  // RFC 5104.
  kRtcpPayloadSpecificFirCode,
  kRtcpPayloadSpecificFirItemCode,

  // RFC 6051.
  kRtcpGenericRtpFeedbackSrReqCode,
};

struct RtcpCommonHeader {
  uint8 V;   // Version.
  bool P;    // Padding.
  uint8 IC;  // Item count / subtype.
  uint8 PT;  // Packet Type.
  uint16 length_in_octets;
};

class RtcpParser {
 public:
  RtcpParser(const uint8* rtcp_data, size_t rtcp_length);
  ~RtcpParser();

  RtcpFieldTypes FieldType() const;
  const RtcpField& Field() const;

  bool IsValid() const;

  RtcpFieldTypes Begin();
  RtcpFieldTypes Iterate();

 private:
  enum ParseState {
    kStateTopLevel,     // Top level packet
    kStateReportBlock,  // Sender/Receiver report report blocks.
    kStateSdes,
    kStateBye,
    kStateApplicationSpecificCastReceiverFrameLog,
    kStateApplicationSpecificCastReceiverEventLog,
    kStateExtendedReportBlock,
    kStateExtendedReportDelaySinceLastReceiverReport,
    kStateGenericRtpFeedbackNack,
    kStatePayloadSpecificRpsi,
    kStatePayloadSpecificFir,
    kStatePayloadSpecificApplication,
    kStatePayloadSpecificRemb,      // Application specific Remb.
    kStatePayloadSpecificCast,      // Application specific Cast.
    kStatePayloadSpecificCastNack,  // Application specific Nack for Cast.
  };

  bool RtcpParseCommonHeader(const uint8* begin,
                             const uint8* end,
                             RtcpCommonHeader* parsed_header) const;

  void IterateTopLevel();
  void IterateReportBlockItem();
  void IterateSdesItem();
  void IterateByeItem();
  void IterateCastReceiverLogFrame();
  void IterateCastReceiverLogEvent();
  void IterateExtendedReportItem();
  void IterateExtendedReportDelaySinceLastReceiverReportItem();
  void IterateNackItem();
  void IterateRpsiItem();
  void IterateFirItem();
  void IteratePayloadSpecificAppItem();
  void IteratePayloadSpecificRembItem();
  void IteratePayloadSpecificCastItem();
  void IteratePayloadSpecificCastNackItem();

  void Validate();
  void EndCurrentBlock();

  bool ParseRR();
  bool ParseSR();
  bool ParseReportBlockItem();

  bool ParseSdes();
  bool ParseSdesItem();
  bool ParseSdesTypes();
  bool ParseBye();
  bool ParseByeItem();
  bool ParseApplicationDefined(uint8 subtype);
  bool ParseCastReceiverLogFrameItem();
  bool ParseCastReceiverLogEventItem();

  bool ParseExtendedReport();
  bool ParseExtendedReportItem();
  bool ParseExtendedReportReceiverReferenceTimeReport();
  bool ParseExtendedReportDelaySinceLastReceiverReport();

  bool ParseFeedBackCommon(const RtcpCommonHeader& header);
  bool ParseNackItem();
  bool ParseRpsiItem();
  bool ParseFirItem();
  bool ParsePayloadSpecificAppItem();
  bool ParsePayloadSpecificRembItem();
  bool ParsePayloadSpecificCastItem();
  bool ParsePayloadSpecificCastNackItem();

 private:
  const uint8* const rtcp_data_begin_;
  const uint8* const rtcp_data_end_;

  bool valid_packet_;
  const uint8* rtcp_data_;
  const uint8* rtcp_block_end_;

  ParseState state_;
  uint8 number_of_blocks_;
  RtcpFieldTypes field_type_;
  RtcpField field_;

  DISALLOW_COPY_AND_ASSIGN(RtcpParser);
};

// Converts a log event type to an integer value.
// NOTE: We have only allocated 4 bits to represent the type of event over the
// wire. Therefore, this function can only return values from 0 to 15.
uint8 ConvertEventTypeToWireFormat(CastLoggingEvent event);

// The inverse of |ConvertEventTypeToWireFormat()|.
CastLoggingEvent TranslateToLogEventFromWireFormat(uint8 event);

}  // namespace cast
}  // namespace media

#endif  // MEDIA_CAST_RTCP_RTCP_UTILITY_H_