blob: dd6260445b24dc2ca1e37ad43a1eac2b4ae12b5d [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h>
14#include <math.h> // ceil
15#include <string.h> // memcpy
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +000016
17#if defined(_WIN32)
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000018// Order for these headers are important
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +000019#include <Windows.h> // FILETIME
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000020
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +000021#include <WinSock.h> // timeval
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000022
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +000023#include <MMSystem.h> // timeGetTime
24#elif ((defined WEBRTC_LINUX) || (defined WEBRTC_MAC))
25#include <sys/time.h> // gettimeofday
26#include <time.h>
27#endif
28#if (defined(_DEBUG) && defined(_WIN32) && (_MSC_VER >= 1400))
29#include <stdio.h>
30#endif
niklase@google.com470e71d2011-07-07 08:21:25 +000031
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000032#include "webrtc/system_wrappers/interface/tick_util.h"
33#include "webrtc/system_wrappers/interface/trace.h"
henrik.lundin@webrtc.org8571af72011-08-29 15:37:12 +000034
niklase@google.com470e71d2011-07-07 08:21:25 +000035#if (defined(_DEBUG) && defined(_WIN32) && (_MSC_VER >= 1400))
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +000036#define DEBUG_PRINT(...) \
37 { \
38 char msg[256]; \
39 sprintf(msg, __VA_ARGS__); \
niklase@google.com470e71d2011-07-07 08:21:25 +000040 OutputDebugString(msg); \
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +000041 }
niklase@google.com470e71d2011-07-07 08:21:25 +000042#else
43// special fix for visual 2003
44#define DEBUG_PRINT(exp) ((void)0)
45#endif // defined(_DEBUG) && defined(_WIN32)
46
niklase@google.com470e71d2011-07-07 08:21:25 +000047namespace webrtc {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000048
wu@webrtc.org822fbd82013-08-15 23:38:54 +000049RtpData* NullObjectRtpData() {
50 static NullRtpData null_rtp_data;
51 return &null_rtp_data;
52}
53
54RtpFeedback* NullObjectRtpFeedback() {
55 static NullRtpFeedback null_rtp_feedback;
56 return &null_rtp_feedback;
57}
58
59RtpAudioFeedback* NullObjectRtpAudioFeedback() {
60 static NullRtpAudioFeedback null_rtp_audio_feedback;
61 return &null_rtp_audio_feedback;
62}
63
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +000064namespace ModuleRTPUtility {
65
solenberg@webrtc.orgd8a6e722013-03-26 14:02:30 +000066enum {
solenberg@webrtc.orga5fd2f12013-06-26 08:36:07 +000067 kRtcpExpectedVersion = 2,
solenberg@webrtc.orgd8a6e722013-03-26 14:02:30 +000068 kRtcpMinHeaderLength = 4,
solenberg@webrtc.orga5fd2f12013-06-26 08:36:07 +000069 kRtcpMinParseLength = 8,
70
71 kRtpExpectedVersion = 2,
72 kRtpMinParseLength = 12
solenberg@webrtc.orgd8a6e722013-03-26 14:02:30 +000073};
74
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000075/*
76 * Time routines.
77 */
78
pbos@webrtc.org2f446732013-04-08 11:08:41 +000079uint32_t GetCurrentRTP(Clock* clock, uint32_t freq) {
henrike@webrtc.orgf5da4da2012-02-15 23:54:59 +000080 const bool use_global_clock = (clock == NULL);
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000081 Clock* local_clock = clock;
henrike@webrtc.orgf5da4da2012-02-15 23:54:59 +000082 if (use_global_clock) {
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000083 local_clock = Clock::GetRealTimeClock();
henrike@webrtc.orgf5da4da2012-02-15 23:54:59 +000084 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +000085 uint32_t secs = 0, frac = 0;
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000086 local_clock->CurrentNtp(secs, frac);
henrike@webrtc.orgf5da4da2012-02-15 23:54:59 +000087 if (use_global_clock) {
88 delete local_clock;
89 }
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +000090 return ConvertNTPTimeToRTP(secs, frac, freq);
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000091}
92
pbos@webrtc.org2f446732013-04-08 11:08:41 +000093uint32_t ConvertNTPTimeToRTP(uint32_t NTPsec, uint32_t NTPfrac, uint32_t freq) {
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +000094 float ftemp = (float)NTPfrac / (float)NTP_FRAC;
pbos@webrtc.org2f446732013-04-08 11:08:41 +000095 uint32_t tmp = (uint32_t)(ftemp * freq);
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +000096 return NTPsec * freq + tmp;
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000097}
98
stefan@webrtc.org7da34592013-04-09 14:56:29 +000099uint32_t ConvertNTPTimeToMS(uint32_t NTPsec, uint32_t NTPfrac) {
100 int freq = 1000;
101 float ftemp = (float)NTPfrac / (float)NTP_FRAC;
102 uint32_t tmp = (uint32_t)(ftemp * freq);
103 uint32_t MStime = NTPsec * freq + tmp;
104 return MStime;
105}
106
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000107/*
108 * Misc utility routines
109 */
110
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000111const uint8_t* GetPayloadData(const RTPHeader& rtp_header,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000112 const uint8_t* packet) {
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000113 return packet + rtp_header.headerLength;
phoglund@webrtc.org07bf43c2012-12-18 15:40:53 +0000114}
115
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000116uint16_t GetPayloadDataLength(const RTPHeader& rtp_header,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000117 const uint16_t packet_length) {
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000118 uint16_t length = packet_length - rtp_header.paddingLength -
119 rtp_header.headerLength;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000120 return static_cast<uint16_t>(length);
phoglund@webrtc.org07bf43c2012-12-18 15:40:53 +0000121}
122
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000123#if defined(_WIN32)
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000124bool StringCompare(const char* str1, const char* str2,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000125 const uint32_t length) {
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000126 return (_strnicmp(str1, str2, length) == 0) ? true : false;
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000127}
128#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000129bool StringCompare(const char* str1, const char* str2,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000130 const uint32_t length) {
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000131 return (strncasecmp(str1, str2, length) == 0) ? true : false;
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000132}
133#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000134
135#if !defined(WEBRTC_LITTLE_ENDIAN) && !defined(WEBRTC_BIG_ENDIAN)
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000136#error Either WEBRTC_LITTLE_ENDIAN or WEBRTC_BIG_ENDIAN must be defined
niklase@google.com470e71d2011-07-07 08:21:25 +0000137#endif
138
139/* for RTP/RTCP
140 All integer fields are carried in network byte order, that is, most
141 significant byte (octet) first. AKA big-endian.
142*/
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000143void AssignUWord32ToBuffer(uint8_t* dataBuffer, uint32_t value) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000144#if defined(WEBRTC_LITTLE_ENDIAN)
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000145 dataBuffer[0] = static_cast<uint8_t>(value >> 24);
146 dataBuffer[1] = static_cast<uint8_t>(value >> 16);
147 dataBuffer[2] = static_cast<uint8_t>(value >> 8);
148 dataBuffer[3] = static_cast<uint8_t>(value);
niklase@google.com470e71d2011-07-07 08:21:25 +0000149#else
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000150 uint32_t* ptr = reinterpret_cast<uint32_t*>(dataBuffer);
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000151 ptr[0] = value;
niklase@google.com470e71d2011-07-07 08:21:25 +0000152#endif
153}
154
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000155void AssignUWord24ToBuffer(uint8_t* dataBuffer, uint32_t value) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000156#if defined(WEBRTC_LITTLE_ENDIAN)
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000157 dataBuffer[0] = static_cast<uint8_t>(value >> 16);
158 dataBuffer[1] = static_cast<uint8_t>(value >> 8);
159 dataBuffer[2] = static_cast<uint8_t>(value);
niklase@google.com470e71d2011-07-07 08:21:25 +0000160#else
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000161 dataBuffer[0] = static_cast<uint8_t>(value);
162 dataBuffer[1] = static_cast<uint8_t>(value >> 8);
163 dataBuffer[2] = static_cast<uint8_t>(value >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000164#endif
165}
166
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000167void AssignUWord16ToBuffer(uint8_t* dataBuffer, uint16_t value) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000168#if defined(WEBRTC_LITTLE_ENDIAN)
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000169 dataBuffer[0] = static_cast<uint8_t>(value >> 8);
170 dataBuffer[1] = static_cast<uint8_t>(value);
niklase@google.com470e71d2011-07-07 08:21:25 +0000171#else
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000172 uint16_t* ptr = reinterpret_cast<uint16_t*>(dataBuffer);
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000173 ptr[0] = value;
niklase@google.com470e71d2011-07-07 08:21:25 +0000174#endif
175}
176
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000177uint16_t BufferToUWord16(const uint8_t* dataBuffer) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000178#if defined(WEBRTC_LITTLE_ENDIAN)
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000179 return (dataBuffer[0] << 8) + dataBuffer[1];
niklase@google.com470e71d2011-07-07 08:21:25 +0000180#else
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000181 return *reinterpret_cast<const uint16_t*>(dataBuffer);
niklase@google.com470e71d2011-07-07 08:21:25 +0000182#endif
183}
184
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000185uint32_t BufferToUWord24(const uint8_t* dataBuffer) {
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000186 return (dataBuffer[0] << 16) + (dataBuffer[1] << 8) + dataBuffer[2];
niklase@google.com470e71d2011-07-07 08:21:25 +0000187}
188
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000189uint32_t BufferToUWord32(const uint8_t* dataBuffer) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000190#if defined(WEBRTC_LITTLE_ENDIAN)
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000191 return (dataBuffer[0] << 24) + (dataBuffer[1] << 16) + (dataBuffer[2] << 8) +
192 dataBuffer[3];
niklase@google.com470e71d2011-07-07 08:21:25 +0000193#else
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000194 return *reinterpret_cast<const uint32_t*>(dataBuffer);
niklase@google.com470e71d2011-07-07 08:21:25 +0000195#endif
196}
197
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000198uint32_t pow2(uint8_t exp) {
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000199 return 1 << exp;
niklase@google.com470e71d2011-07-07 08:21:25 +0000200}
201
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000202void RTPPayload::SetType(RtpVideoCodecTypes videoType) {
203 type = videoType;
niklase@google.com470e71d2011-07-07 08:21:25 +0000204
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000205 switch (type) {
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000206 case kRtpVideoGeneric:
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000207 break;
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000208 case kRtpVideoVp8: {
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000209 info.VP8.nonReferenceFrame = false;
210 info.VP8.beginningOfPartition = false;
211 info.VP8.partitionID = 0;
212 info.VP8.hasPictureID = false;
213 info.VP8.hasTl0PicIdx = false;
214 info.VP8.hasTID = false;
215 info.VP8.hasKeyIdx = false;
216 info.VP8.pictureID = -1;
217 info.VP8.tl0PicIdx = -1;
218 info.VP8.tID = -1;
219 info.VP8.layerSync = false;
220 info.VP8.frameWidth = 0;
221 info.VP8.frameHeight = 0;
222 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000223 }
224 default:
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000225 break;
226 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000227}
228
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000229RTPHeaderParser::RTPHeaderParser(const uint8_t* rtpData,
230 const uint32_t rtpDataLength)
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000231 : _ptrRTPDataBegin(rtpData),
232 _ptrRTPDataEnd(rtpData ? (rtpData + rtpDataLength) : NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000233}
234
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000235RTPHeaderParser::~RTPHeaderParser() {
niklase@google.com470e71d2011-07-07 08:21:25 +0000236}
237
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000238bool RTPHeaderParser::RTCP() const {
239 // 72 to 76 is reserved for RTP
240 // 77 to 79 is not reserver but they are not assigned we will block them
241 // for RTCP 200 SR == marker bit + 72
242 // for RTCP 204 APP == marker bit + 76
243 /*
244 * RTCP
245 *
246 * FIR full INTRA-frame request 192 [RFC2032] supported
247 * NACK negative acknowledgement 193 [RFC2032]
248 * IJ Extended inter-arrival jitter report 195 [RFC-ietf-avt-rtp-toff
249 * set-07.txt] http://tools.ietf.org/html/draft-ietf-avt-rtp-toffset-07
250 * SR sender report 200 [RFC3551] supported
251 * RR receiver report 201 [RFC3551] supported
252 * SDES source description 202 [RFC3551] supported
253 * BYE goodbye 203 [RFC3551] supported
254 * APP application-defined 204 [RFC3551] ignored
255 * RTPFB Transport layer FB message 205 [RFC4585] supported
256 * PSFB Payload-specific FB message 206 [RFC4585] supported
257 * XR extended report 207 [RFC3611] supported
258 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000259
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000260 /* 205 RFC 5104
261 * FMT 1 NACK supported
262 * FMT 2 reserved
263 * FMT 3 TMMBR supported
264 * FMT 4 TMMBN supported
265 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000266
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000267 /* 206 RFC 5104
268 * FMT 1: Picture Loss Indication (PLI) supported
269 * FMT 2: Slice Lost Indication (SLI)
270 * FMT 3: Reference Picture Selection Indication (RPSI)
271 * FMT 4: Full Intra Request (FIR) Command supported
272 * FMT 5: Temporal-Spatial Trade-off Request (TSTR)
273 * FMT 6: Temporal-Spatial Trade-off Notification (TSTN)
274 * FMT 7: Video Back Channel Message (VBCM)
275 * FMT 15: Application layer FB message
276 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000277
solenberg@webrtc.orgd8a6e722013-03-26 14:02:30 +0000278 const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
279 if (length < kRtcpMinHeaderLength) {
280 return false;
281 }
282
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000283 const uint8_t V = _ptrRTPDataBegin[0] >> 6;
solenberg@webrtc.orgd8a6e722013-03-26 14:02:30 +0000284 if (V != kRtcpExpectedVersion) {
285 return false;
286 }
287
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000288 const uint8_t payloadType = _ptrRTPDataBegin[1];
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000289 bool RTCP = false;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000290 switch (payloadType) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000291 case 192:
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000292 RTCP = true;
293 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000294 case 193:
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000295 // not supported
296 // pass through and check for a potential RTP packet
297 break;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000298 case 195:
niklase@google.com470e71d2011-07-07 08:21:25 +0000299 case 200:
300 case 201:
301 case 202:
302 case 203:
303 case 204:
304 case 205:
305 case 206:
306 case 207:
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000307 RTCP = true;
308 break;
309 }
310 return RTCP;
niklase@google.com470e71d2011-07-07 08:21:25 +0000311}
312
solenberg@webrtc.orga5fd2f12013-06-26 08:36:07 +0000313bool RTPHeaderParser::ParseRtcp(RTPHeader* header) const {
314 assert(header != NULL);
315
316 const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
317 if (length < kRtcpMinParseLength) {
318 return false;
319 }
320
321 const uint8_t V = _ptrRTPDataBegin[0] >> 6;
322 if (V != kRtcpExpectedVersion) {
323 return false;
324 }
325
326 const uint8_t PT = _ptrRTPDataBegin[1];
327 const uint16_t len = (_ptrRTPDataBegin[2] << 8) + _ptrRTPDataBegin[3];
328 const uint8_t* ptr = &_ptrRTPDataBegin[4];
329
330 uint32_t SSRC = *ptr++ << 24;
331 SSRC += *ptr++ << 16;
332 SSRC += *ptr++ << 8;
333 SSRC += *ptr++;
334
335 header->payloadType = PT;
336 header->ssrc = SSRC;
337 header->headerLength = 4 + (len << 2);
338
339 return true;
340}
341
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000342bool RTPHeaderParser::Parse(RTPHeader& header,
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000343 RtpHeaderExtensionMap* ptrExtensionMap) const {
344 const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
solenberg@webrtc.orga5fd2f12013-06-26 08:36:07 +0000345 if (length < kRtpMinParseLength) {
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000346 return false;
347 }
348
349 // Version
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000350 const uint8_t V = _ptrRTPDataBegin[0] >> 6;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000351 // Padding
352 const bool P = ((_ptrRTPDataBegin[0] & 0x20) == 0) ? false : true;
353 // eXtension
354 const bool X = ((_ptrRTPDataBegin[0] & 0x10) == 0) ? false : true;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000355 const uint8_t CC = _ptrRTPDataBegin[0] & 0x0f;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000356 const bool M = ((_ptrRTPDataBegin[1] & 0x80) == 0) ? false : true;
357
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000358 const uint8_t PT = _ptrRTPDataBegin[1] & 0x7f;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000359
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000360 const uint16_t sequenceNumber = (_ptrRTPDataBegin[2] << 8) +
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000361 _ptrRTPDataBegin[3];
362
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000363 const uint8_t* ptr = &_ptrRTPDataBegin[4];
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000364
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000365 uint32_t RTPTimestamp = *ptr++ << 24;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000366 RTPTimestamp += *ptr++ << 16;
367 RTPTimestamp += *ptr++ << 8;
368 RTPTimestamp += *ptr++;
369
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000370 uint32_t SSRC = *ptr++ << 24;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000371 SSRC += *ptr++ << 16;
372 SSRC += *ptr++ << 8;
373 SSRC += *ptr++;
374
solenberg@webrtc.orga5fd2f12013-06-26 08:36:07 +0000375 if (V != kRtpExpectedVersion) {
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000376 return false;
377 }
378
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000379 const uint8_t CSRCocts = CC * 4;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000380
381 if ((ptr + CSRCocts) > _ptrRTPDataEnd) {
382 return false;
383 }
384
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000385 header.markerBit = M;
386 header.payloadType = PT;
387 header.sequenceNumber = sequenceNumber;
388 header.timestamp = RTPTimestamp;
389 header.ssrc = SSRC;
390 header.numCSRCs = CC;
391 header.paddingLength = P ? *(_ptrRTPDataEnd - 1) : 0;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000392
393 for (unsigned int i = 0; i < CC; ++i) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000394 uint32_t CSRC = *ptr++ << 24;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000395 CSRC += *ptr++ << 16;
396 CSRC += *ptr++ << 8;
397 CSRC += *ptr++;
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000398 header.arrOfCSRCs[i] = CSRC;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000399 }
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000400
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000401 header.headerLength = 12 + CSRCocts;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000402
403 // If in effect, MAY be omitted for those packets for which the offset
404 // is zero.
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000405 header.extension.transmissionTimeOffset = 0;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000406
solenberg@webrtc.org7ebbea12013-05-16 11:10:31 +0000407 // May not be present in packet.
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000408 header.extension.absoluteSendTime = 0;
solenberg@webrtc.org7ebbea12013-05-16 11:10:31 +0000409
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000410 if (X) {
411 /* RTP header extension, RFC 3550.
412 0 1 2 3
413 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
414 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
415 | defined by profile | length |
416 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
417 | header extension |
418 | .... |
419 */
420 const ptrdiff_t remain = _ptrRTPDataEnd - ptr;
421 if (remain < 4) {
422 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000423 }
424
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000425 header.headerLength += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000426
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000427 uint16_t definedByProfile = *ptr++ << 8;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000428 definedByProfile += *ptr++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000429
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000430 uint16_t XLen = *ptr++ << 8;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000431 XLen += *ptr++; // in 32 bit words
432 XLen *= 4; // in octs
niklase@google.com470e71d2011-07-07 08:21:25 +0000433
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000434 if (remain < (4 + XLen)) {
435 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000436 }
pbos@webrtc.org3004c792013-05-07 12:36:21 +0000437 if (definedByProfile == kRtpOneByteHeaderExtensionId) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000438 const uint8_t* ptrRTPDataExtensionEnd = ptr + XLen;
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000439 ParseOneByteExtensionHeader(header,
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000440 ptrExtensionMap,
441 ptrRTPDataExtensionEnd,
442 ptr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000443 }
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000444 header.headerLength += XLen;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000445 }
446 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000447}
448
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000449void RTPHeaderParser::ParseOneByteExtensionHeader(
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000450 RTPHeader& header,
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000451 const RtpHeaderExtensionMap* ptrExtensionMap,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000452 const uint8_t* ptrRTPDataExtensionEnd,
453 const uint8_t* ptr) const {
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000454 if (!ptrExtensionMap) {
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000455 return;
456 }
457
458 while (ptrRTPDataExtensionEnd - ptr > 0) {
459 // 0
460 // 0 1 2 3 4 5 6 7
461 // +-+-+-+-+-+-+-+-+
462 // | ID | len |
463 // +-+-+-+-+-+-+-+-+
464
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000465 const uint8_t id = (*ptr & 0xf0) >> 4;
466 const uint8_t len = (*ptr & 0x0f);
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000467 ptr++;
468
469 if (id == 15) {
470 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, -1,
471 "Ext id: 15 encountered, parsing terminated.");
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000472 return;
473 }
474
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000475 RTPExtensionType type;
476 if (ptrExtensionMap->GetType(id, &type) != 0) {
477 WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
478 "Failed to find extension id: %d", id);
479 return;
480 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000481
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000482 switch (type) {
483 case kRtpExtensionTransmissionTimeOffset: {
484 if (len != 2) {
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000485 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, -1,
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000486 "Incorrect transmission time offset len: %d", len);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000487 return;
488 }
489 // 0 1 2 3
490 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
491 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
492 // | ID | len=2 | transmission offset |
493 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
494
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000495 int32_t transmissionTimeOffset = *ptr++ << 16;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000496 transmissionTimeOffset += *ptr++ << 8;
497 transmissionTimeOffset += *ptr++;
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000498 header.extension.transmissionTimeOffset =
499 transmissionTimeOffset;
asapersson@webrtc.orgd2e67792012-06-28 07:53:15 +0000500 if (transmissionTimeOffset & 0x800000) {
501 // Negative offset, correct sign for Word24 to Word32.
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000502 header.extension.transmissionTimeOffset |= 0xFF000000;
asapersson@webrtc.orgd2e67792012-06-28 07:53:15 +0000503 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000504 break;
505 }
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000506 case kRtpExtensionAudioLevel: {
507 // --- Only used for debugging ---
508 // 0 1 2 3
509 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
510 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
511 // | ID | len=0 |V| level | 0x00 | 0x00 |
512 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
513 //
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000514
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000515 // Parse out the fields but only use it for debugging for now.
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000516 // const uint8_t V = (*ptr & 0x80) >> 7;
517 // const uint8_t level = (*ptr & 0x7f);
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000518 // DEBUG_PRINT("RTP_AUDIO_LEVEL_UNIQUE_ID: ID=%u, len=%u, V=%u,
519 // level=%u", ID, len, V, level);
pwestin@webrtc.org6c1d4152012-01-04 17:04:51 +0000520 break;
521 }
solenberg@webrtc.org7ebbea12013-05-16 11:10:31 +0000522 case kRtpExtensionAbsoluteSendTime: {
523 if (len != 2) {
524 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, -1,
525 "Incorrect absolute send time len: %d", len);
526 return;
527 }
528 // 0 1 2 3
529 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
530 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
531 // | ID | len=2 | absolute send time |
532 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
533
534 uint32_t absoluteSendTime = *ptr++ << 16;
535 absoluteSendTime += *ptr++ << 8;
536 absoluteSendTime += *ptr++;
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000537 header.extension.absoluteSendTime = absoluteSendTime;
solenberg@webrtc.org7ebbea12013-05-16 11:10:31 +0000538 break;
539 }
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000540 default: {
mflodman@webrtc.orgba853c92012-08-10 14:30:53 +0000541 WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000542 "Extension type not implemented.");
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000543 return;
544 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000545 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000546 uint8_t num_bytes = ParsePaddingBytes(ptrRTPDataExtensionEnd, ptr);
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000547 ptr += num_bytes;
548 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000549}
550
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000551uint8_t RTPHeaderParser::ParsePaddingBytes(
552 const uint8_t* ptrRTPDataExtensionEnd,
553 const uint8_t* ptr) const {
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000554
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000555 uint8_t num_zero_bytes = 0;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000556 while (ptrRTPDataExtensionEnd - ptr > 0) {
557 if (*ptr != 0) {
558 return num_zero_bytes;
559 }
560 ptr++;
561 num_zero_bytes++;
562 }
563 return num_zero_bytes;
564}
565
niklase@google.com470e71d2011-07-07 08:21:25 +0000566// RTP payload parser
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000567RTPPayloadParser::RTPPayloadParser(const RtpVideoCodecTypes videoType,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000568 const uint8_t* payloadData,
569 uint16_t payloadDataLength,
570 int32_t id)
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000571 :
572 _id(id),
573 _dataPtr(payloadData),
574 _dataLength(payloadDataLength),
575 _videoType(videoType) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000576}
577
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000578RTPPayloadParser::~RTPPayloadParser() {
niklase@google.com470e71d2011-07-07 08:21:25 +0000579}
580
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000581bool RTPPayloadParser::Parse(RTPPayload& parsedPacket) const {
582 parsedPacket.SetType(_videoType);
niklase@google.com470e71d2011-07-07 08:21:25 +0000583
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000584 switch (_videoType) {
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000585 case kRtpVideoGeneric:
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000586 return ParseGeneric(parsedPacket);
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000587 case kRtpVideoVp8:
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000588 return ParseVP8(parsedPacket);
niklase@google.com470e71d2011-07-07 08:21:25 +0000589 default:
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000590 return false;
591 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000592}
593
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000594bool RTPPayloadParser::ParseGeneric(RTPPayload& /*parsedPacket*/) const {
595 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000596}
597
henrik.lundin@webrtc.org8571af72011-08-29 15:37:12 +0000598//
599// VP8 format:
600//
601// Payload descriptor
henrik.lundin@webrtc.org6f2c0162011-11-24 12:52:40 +0000602// 0 1 2 3 4 5 6 7
603// +-+-+-+-+-+-+-+-+
604// |X|R|N|S|PartID | (REQUIRED)
605// +-+-+-+-+-+-+-+-+
606// X: |I|L|T|K| RSV | (OPTIONAL)
607// +-+-+-+-+-+-+-+-+
608// I: | PictureID | (OPTIONAL)
609// +-+-+-+-+-+-+-+-+
610// L: | TL0PICIDX | (OPTIONAL)
611// +-+-+-+-+-+-+-+-+
henrik.lundin@webrtc.orgeda86dc2011-12-13 14:11:06 +0000612// T/K: |TID:Y| KEYIDX | (OPTIONAL)
henrik.lundin@webrtc.org6f2c0162011-11-24 12:52:40 +0000613// +-+-+-+-+-+-+-+-+
henrik.lundin@webrtc.org8571af72011-08-29 15:37:12 +0000614//
615// Payload header (considered part of the actual payload, sent to decoder)
henrik.lundin@webrtc.org6f2c0162011-11-24 12:52:40 +0000616// 0 1 2 3 4 5 6 7
617// +-+-+-+-+-+-+-+-+
618// |Size0|H| VER |P|
619// +-+-+-+-+-+-+-+-+
620// | ... |
621// + +
henrik.lundin@webrtc.org8571af72011-08-29 15:37:12 +0000622
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000623bool RTPPayloadParser::ParseVP8(RTPPayload& parsedPacket) const {
624 RTPPayloadVP8* vp8 = &parsedPacket.info.VP8;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000625 const uint8_t* dataPtr = _dataPtr;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000626 int dataLength = _dataLength;
niklase@google.com470e71d2011-07-07 08:21:25 +0000627
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000628 // Parse mandatory first byte of payload descriptor
629 bool extension = (*dataPtr & 0x80) ? true : false; // X bit
630 vp8->nonReferenceFrame = (*dataPtr & 0x20) ? true : false; // N bit
631 vp8->beginningOfPartition = (*dataPtr & 0x10) ? true : false; // S bit
632 vp8->partitionID = (*dataPtr & 0x0F); // PartID field
henrik.lundin@webrtc.org8571af72011-08-29 15:37:12 +0000633
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000634 if (vp8->partitionID > 8) {
635 // Weak check for corrupt data: PartID MUST NOT be larger than 8.
636 return false;
637 }
andrew@webrtc.org7fe219f2012-02-01 02:40:37 +0000638
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000639 // Advance dataPtr and decrease remaining payload size
640 dataPtr++;
641 dataLength--;
henrik.lundin@webrtc.org8571af72011-08-29 15:37:12 +0000642
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000643 if (extension) {
644 const int parsedBytes = ParseVP8Extension(vp8, dataPtr, dataLength);
645 if (parsedBytes < 0) return false;
646 dataPtr += parsedBytes;
647 dataLength -= parsedBytes;
648 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000649
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000650 if (dataLength <= 0) {
651 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
652 "Error parsing VP8 payload descriptor; payload too short");
653 return false;
654 }
henrik.lundin@webrtc.org8571af72011-08-29 15:37:12 +0000655
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000656 // Read P bit from payload header (only at beginning of first partition)
657 if (dataLength > 0 && vp8->beginningOfPartition && vp8->partitionID == 0) {
658 parsedPacket.frameType = (*dataPtr & 0x01) ? kPFrame : kIFrame;
659 } else {
660 parsedPacket.frameType = kPFrame;
661 }
662 if (0 != ParseVP8FrameSize(parsedPacket, dataPtr, dataLength)) {
663 return false;
664 }
665 parsedPacket.info.VP8.data = dataPtr;
666 parsedPacket.info.VP8.dataLength = dataLength;
667 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000668}
669
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000670int RTPPayloadParser::ParseVP8FrameSize(RTPPayload& parsedPacket,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000671 const uint8_t* dataPtr,
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000672 int dataLength) const {
673 if (parsedPacket.frameType != kIFrame) {
674 // Included in payload header for I-frames.
pwestin@webrtc.org075e91f2011-11-02 23:14:58 +0000675 return 0;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000676 }
677 if (dataLength < 10) {
678 // For an I-frame we should always have the uncompressed VP8 header
679 // in the beginning of the partition.
680 return -1;
681 }
682 RTPPayloadVP8* vp8 = &parsedPacket.info.VP8;
683 vp8->frameWidth = ((dataPtr[7] << 8) + dataPtr[6]) & 0x3FFF;
684 vp8->frameHeight = ((dataPtr[9] << 8) + dataPtr[8]) & 0x3FFF;
685 return 0;
pwestin@webrtc.org075e91f2011-11-02 23:14:58 +0000686}
687
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000688int RTPPayloadParser::ParseVP8Extension(RTPPayloadVP8* vp8,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000689 const uint8_t* dataPtr,
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000690 int dataLength) const {
691 int parsedBytes = 0;
692 if (dataLength <= 0) return -1;
693 // Optional X field is present
694 vp8->hasPictureID = (*dataPtr & 0x80) ? true : false; // I bit
695 vp8->hasTl0PicIdx = (*dataPtr & 0x40) ? true : false; // L bit
696 vp8->hasTID = (*dataPtr & 0x20) ? true : false; // T bit
697 vp8->hasKeyIdx = (*dataPtr & 0x10) ? true : false; // K bit
henrik.lundin@webrtc.org8571af72011-08-29 15:37:12 +0000698
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000699 // Advance dataPtr and decrease remaining payload size
700 dataPtr++;
701 parsedBytes++;
702 dataLength--;
henrik.lundin@webrtc.org8571af72011-08-29 15:37:12 +0000703
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000704 if (vp8->hasPictureID) {
705 if (ParseVP8PictureID(vp8, &dataPtr, &dataLength, &parsedBytes) != 0) {
706 return -1;
henrik.lundin@webrtc.org8571af72011-08-29 15:37:12 +0000707 }
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000708 }
henrik.lundin@webrtc.org8571af72011-08-29 15:37:12 +0000709
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000710 if (vp8->hasTl0PicIdx) {
711 if (ParseVP8Tl0PicIdx(vp8, &dataPtr, &dataLength, &parsedBytes) != 0) {
712 return -1;
henrik.lundin@webrtc.org8571af72011-08-29 15:37:12 +0000713 }
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000714 }
henrik.lundin@webrtc.org8571af72011-08-29 15:37:12 +0000715
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000716 if (vp8->hasTID || vp8->hasKeyIdx) {
717 if (ParseVP8TIDAndKeyIdx(vp8, &dataPtr, &dataLength, &parsedBytes) != 0) {
718 return -1;
henrik.lundin@webrtc.org8571af72011-08-29 15:37:12 +0000719 }
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000720 }
721 return parsedBytes;
henrik.lundin@webrtc.org8571af72011-08-29 15:37:12 +0000722}
723
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000724int RTPPayloadParser::ParseVP8PictureID(RTPPayloadVP8* vp8,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000725 const uint8_t** dataPtr,
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000726 int* dataLength,
727 int* parsedBytes) const {
728 if (*dataLength <= 0) return -1;
729 vp8->pictureID = (**dataPtr & 0x7F);
730 if (**dataPtr & 0x80) {
henrik.lundin@webrtc.org8571af72011-08-29 15:37:12 +0000731 (*dataPtr)++;
732 (*parsedBytes)++;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000733 if (--(*dataLength) <= 0) return -1;
734 // PictureID is 15 bits
735 vp8->pictureID = (vp8->pictureID << 8) +** dataPtr;
736 }
737 (*dataPtr)++;
738 (*parsedBytes)++;
739 (*dataLength)--;
740 return 0;
henrik.lundin@webrtc.org8571af72011-08-29 15:37:12 +0000741}
742
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000743int RTPPayloadParser::ParseVP8Tl0PicIdx(RTPPayloadVP8* vp8,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000744 const uint8_t** dataPtr,
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000745 int* dataLength,
746 int* parsedBytes) const {
747 if (*dataLength <= 0) return -1;
748 vp8->tl0PicIdx = **dataPtr;
749 (*dataPtr)++;
750 (*parsedBytes)++;
751 (*dataLength)--;
752 return 0;
henrik.lundin@webrtc.org8571af72011-08-29 15:37:12 +0000753}
754
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000755int RTPPayloadParser::ParseVP8TIDAndKeyIdx(RTPPayloadVP8* vp8,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000756 const uint8_t** dataPtr,
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000757 int* dataLength,
758 int* parsedBytes) const {
759 if (*dataLength <= 0) return -1;
760 if (vp8->hasTID) {
761 vp8->tID = ((**dataPtr >> 6) & 0x03);
762 vp8->layerSync = (**dataPtr & 0x20) ? true : false; // Y bit
763 }
764 if (vp8->hasKeyIdx) {
765 vp8->keyIdx = (**dataPtr & 0x1F);
766 }
767 (*dataPtr)++;
768 (*parsedBytes)++;
769 (*dataLength)--;
770 return 0;
henrik.lundin@webrtc.org8571af72011-08-29 15:37:12 +0000771}
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000772
773} // namespace ModuleRTPUtility
774
775} // namespace webrtc