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