1e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org/*
2e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org *
4e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org *  Use of this source code is governed by a BSD-style license
5e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org *  that can be found in the LICENSE file in the root of the source
6e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org *  tree. An additional intellectual property rights grant can be found
7e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org *  in the file PATENTS.  All contributing project authors may
8e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org */
10e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org
11e5abc854f3dc47de16067c2a41476c39b7626722henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/tools/packet.h"
12655819eb8dfd638d060c3cdd1ba37fe0a47d0cafhenrik.lundin@webrtc.org
13655819eb8dfd638d060c3cdd1ba37fe0a47d0cafhenrik.lundin@webrtc.org#include <string.h>
14655819eb8dfd638d060c3cdd1ba37fe0a47d0cafhenrik.lundin@webrtc.org
15655819eb8dfd638d060c3cdd1ba37fe0a47d0cafhenrik.lundin@webrtc.org#include "webrtc/modules/interface/module_common_types.h"
16e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
17e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org
18e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.orgnamespace webrtc {
19e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.orgnamespace test {
20e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org
21e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.orgPacket::Packet(uint8_t* packet_memory,
22e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org               size_t allocated_bytes,
23e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org               double time_ms,
24e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org               const RtpHeaderParser& parser)
25e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org    : payload_memory_(packet_memory),
26e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      payload_(NULL),
27e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      packet_length_bytes_(allocated_bytes),
28e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      payload_length_bytes_(0),
29e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      virtual_packet_length_bytes_(allocated_bytes),
30e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      virtual_payload_length_bytes_(0),
31e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      time_ms_(time_ms) {
32e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  valid_header_ = ParseHeader(parser);
33e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org}
34e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org
35e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.orgPacket::Packet(uint8_t* packet_memory,
36e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org               size_t allocated_bytes,
37e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org               size_t virtual_packet_length_bytes,
38e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org               double time_ms,
39e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org               const RtpHeaderParser& parser)
40e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org    : payload_memory_(packet_memory),
41e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      payload_(NULL),
42e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      packet_length_bytes_(allocated_bytes),
43e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      payload_length_bytes_(0),
44e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      virtual_packet_length_bytes_(virtual_packet_length_bytes),
45e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      virtual_payload_length_bytes_(0),
46e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      time_ms_(time_ms) {
47e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  valid_header_ = ParseHeader(parser);
48e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org}
49e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org
50e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.orgPacket::Packet(uint8_t* packet_memory, size_t allocated_bytes, double time_ms)
51e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org    : payload_memory_(packet_memory),
52e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      payload_(NULL),
53e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      packet_length_bytes_(allocated_bytes),
54e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      payload_length_bytes_(0),
55e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      virtual_packet_length_bytes_(allocated_bytes),
56e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      virtual_payload_length_bytes_(0),
57e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      time_ms_(time_ms) {
58e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
59e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  valid_header_ = ParseHeader(*parser);
60e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org}
61e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org
62e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.orgPacket::Packet(uint8_t* packet_memory,
63e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org               size_t allocated_bytes,
64e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org               size_t virtual_packet_length_bytes,
65e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org               double time_ms)
66e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org    : payload_memory_(packet_memory),
67e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      payload_(NULL),
68e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      packet_length_bytes_(allocated_bytes),
69e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      payload_length_bytes_(0),
70e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      virtual_packet_length_bytes_(virtual_packet_length_bytes),
71e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      virtual_payload_length_bytes_(0),
72e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      time_ms_(time_ms) {
73e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
74e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  valid_header_ = ParseHeader(*parser);
75e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org}
76e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org
77e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.orgbool Packet::ExtractRedHeaders(std::list<RTPHeader*>* headers) const {
78e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  //
79e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  //  0                   1                    2                   3
80e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  //  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
81e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
82e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  // |1|   block PT  |  timestamp offset         |   block length    |
83e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
84e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  // |1|    ...                                                      |
85e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
86e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  // |0|   block PT  |
87e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  // +-+-+-+-+-+-+-+-+
88e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  //
89e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org
90e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  assert(payload_);
91e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  const uint8_t* payload_ptr = payload_;
92e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  const uint8_t* payload_end_ptr = payload_ptr + payload_length_bytes_;
93e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org
94e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  // Find all RED headers with the extension bit set to 1. That is, all headers
95e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  // but the last one.
96e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  while ((payload_ptr < payload_end_ptr) && (*payload_ptr & 0x80)) {
97e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org    RTPHeader* header = new RTPHeader;
98e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org    CopyToHeader(header);
99e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org    header->payloadType = payload_ptr[0] & 0x7F;
100e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org    uint32_t offset = (payload_ptr[1] << 6) + ((payload_ptr[2] & 0xFC) >> 2);
101e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org    header->timestamp -= offset;
102e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org    headers->push_front(header);
103e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org    payload_ptr += 4;
104e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  }
105e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  // Last header.
106e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  assert(payload_ptr < payload_end_ptr);
107e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  if (payload_ptr >= payload_end_ptr) {
108e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org    return false;  // Payload too short.
109e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  }
110e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  RTPHeader* header = new RTPHeader;
111e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  CopyToHeader(header);
112e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  header->payloadType = payload_ptr[0] & 0x7F;
113e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  headers->push_front(header);
114e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  return true;
115e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org}
116e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org
117e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.orgvoid Packet::DeleteRedHeaders(std::list<RTPHeader*>* headers) {
118e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  while (!headers->empty()) {
119e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org    delete headers->front();
120e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org    headers->pop_front();
121e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  }
122e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org}
123e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org
124655819eb8dfd638d060c3cdd1ba37fe0a47d0cafhenrik.lundin@webrtc.orgvoid Packet::ConvertHeader(WebRtcRTPHeader* copy_to) const {
125655819eb8dfd638d060c3cdd1ba37fe0a47d0cafhenrik.lundin@webrtc.org  memcpy(&copy_to->header, &header_, sizeof(header_));
126655819eb8dfd638d060c3cdd1ba37fe0a47d0cafhenrik.lundin@webrtc.org  copy_to->frameType = kAudioFrameSpeech;
127655819eb8dfd638d060c3cdd1ba37fe0a47d0cafhenrik.lundin@webrtc.org  copy_to->type.Audio.numEnergy = 0;
128655819eb8dfd638d060c3cdd1ba37fe0a47d0cafhenrik.lundin@webrtc.org  copy_to->type.Audio.channel = 1;
129655819eb8dfd638d060c3cdd1ba37fe0a47d0cafhenrik.lundin@webrtc.org  copy_to->type.Audio.isCNG = false;
130655819eb8dfd638d060c3cdd1ba37fe0a47d0cafhenrik.lundin@webrtc.org}
131655819eb8dfd638d060c3cdd1ba37fe0a47d0cafhenrik.lundin@webrtc.org
132e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.orgbool Packet::ParseHeader(const RtpHeaderParser& parser) {
133e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  bool valid_header = parser.Parse(
134e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      payload_memory_.get(), static_cast<int>(packet_length_bytes_), &header_);
135e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  assert(valid_header);
136e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  if (!valid_header) {
137e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org    return false;
138e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  }
139e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  assert(header_.headerLength <= packet_length_bytes_);
140e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  payload_ = &payload_memory_[header_.headerLength];
141e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  assert(packet_length_bytes_ >= header_.headerLength);
142e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  payload_length_bytes_ = packet_length_bytes_ - header_.headerLength;
143e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  assert(virtual_packet_length_bytes_ >= header_.headerLength);
144e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  virtual_payload_length_bytes_ =
145e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      virtual_packet_length_bytes_ - header_.headerLength;
146e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  return true;
147e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org}
148e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org
149e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.orgvoid Packet::CopyToHeader(RTPHeader* destination) const {
150e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  destination->markerBit = header_.markerBit;
151e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  destination->payloadType = header_.payloadType;
152e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  destination->sequenceNumber = header_.sequenceNumber;
153e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  destination->timestamp = header_.timestamp;
154e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  destination->ssrc = header_.ssrc;
155e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  destination->numCSRCs = header_.numCSRCs;
156e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  destination->paddingLength = header_.paddingLength;
157e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  destination->headerLength = header_.headerLength;
158e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  destination->payload_type_frequency = header_.payload_type_frequency;
159e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  memcpy(&destination->arrOfCSRCs,
160e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org         &header_.arrOfCSRCs,
161e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org         sizeof(header_.arrOfCSRCs));
162e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org  memcpy(
163e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org      &destination->extension, &header_.extension, sizeof(header_.extension));
164e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org}
165e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org
166e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org}  // namespace test
167e7d9de31cd13fb915c858c54a84ab39f788c3c69henrik.lundin@webrtc.org}  // namespace webrtc
168