Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Side by Side Diff: webrtc/modules/audio_coding/neteq/red_payload_splitter.cc

Issue 2425223002: NetEq now works with packets as values, rather than pointers. (Closed)
Patch Set: Compare packets better in test. One more const. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 16 matching lines...) Expand all
27 // is replaced by the new ones in |new_packets|, so that |packet_list| becomes: 27 // is replaced by the new ones in |new_packets|, so that |packet_list| becomes:
28 // {A1, A2, ..., B, C, ...}. The method then continues with B, and C, until all 28 // {A1, A2, ..., B, C, ...}. The method then continues with B, and C, until all
29 // the original packets have been replaced by their split payloads. 29 // the original packets have been replaced by their split payloads.
30 bool RedPayloadSplitter::SplitRed(PacketList* packet_list) { 30 bool RedPayloadSplitter::SplitRed(PacketList* packet_list) {
31 // Too many RED blocks indicates that something is wrong. Clamp it at some 31 // Too many RED blocks indicates that something is wrong. Clamp it at some
32 // reasonable value. 32 // reasonable value.
33 const size_t kMaxRedBlocks = 32; 33 const size_t kMaxRedBlocks = 32;
34 bool ret = true; 34 bool ret = true;
35 PacketList::iterator it = packet_list->begin(); 35 PacketList::iterator it = packet_list->begin();
36 while (it != packet_list->end()) { 36 while (it != packet_list->end()) {
37 const Packet* red_packet = (*it); 37 const Packet& red_packet = *it;
38 assert(!red_packet->payload.empty()); 38 assert(!red_packet.payload.empty());
39 const uint8_t* payload_ptr = red_packet->payload.data(); 39 const uint8_t* payload_ptr = red_packet.payload.data();
40 40
41 // Read RED headers (according to RFC 2198): 41 // Read RED headers (according to RFC 2198):
42 // 42 //
43 // 0 1 2 3 43 // 0 1 2 3
44 // 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 44 // 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
45 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 45 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46 // |F| block PT | timestamp offset | block length | 46 // |F| block PT | timestamp offset | block length |
47 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 47 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48 // Last RED header: 48 // Last RED header:
49 // 0 1 2 3 4 5 6 7 49 // 0 1 2 3 4 5 6 7
(...skipping 12 matching lines...) Expand all
62 size_t sum_length = 0; 62 size_t sum_length = 0;
63 while (!last_block) { 63 while (!last_block) {
64 RedHeader new_header; 64 RedHeader new_header;
65 // Check the F bit. If F == 0, this was the last block. 65 // Check the F bit. If F == 0, this was the last block.
66 last_block = ((*payload_ptr & 0x80) == 0); 66 last_block = ((*payload_ptr & 0x80) == 0);
67 // Bits 1 through 7 are payload type. 67 // Bits 1 through 7 are payload type.
68 new_header.payload_type = payload_ptr[0] & 0x7F; 68 new_header.payload_type = payload_ptr[0] & 0x7F;
69 if (last_block) { 69 if (last_block) {
70 // No more header data to read. 70 // No more header data to read.
71 ++sum_length; // Account for RED header size of 1 byte. 71 ++sum_length; // Account for RED header size of 1 byte.
72 new_header.timestamp = red_packet->timestamp; 72 new_header.timestamp = red_packet.timestamp;
73 new_header.payload_length = red_packet->payload.size() - sum_length; 73 new_header.payload_length = red_packet.payload.size() - sum_length;
74 payload_ptr += 1; // Advance to first payload byte. 74 payload_ptr += 1; // Advance to first payload byte.
75 } else { 75 } else {
76 // Bits 8 through 21 are timestamp offset. 76 // Bits 8 through 21 are timestamp offset.
77 int timestamp_offset = 77 int timestamp_offset =
78 (payload_ptr[1] << 6) + ((payload_ptr[2] & 0xFC) >> 2); 78 (payload_ptr[1] << 6) + ((payload_ptr[2] & 0xFC) >> 2);
79 new_header.timestamp = red_packet->timestamp - timestamp_offset; 79 new_header.timestamp = red_packet.timestamp - timestamp_offset;
80 // Bits 22 through 31 are payload length. 80 // Bits 22 through 31 are payload length.
81 new_header.payload_length = 81 new_header.payload_length =
82 ((payload_ptr[2] & 0x03) << 8) + payload_ptr[3]; 82 ((payload_ptr[2] & 0x03) << 8) + payload_ptr[3];
83 payload_ptr += 4; // Advance to next RED header. 83 payload_ptr += 4; // Advance to next RED header.
84 } 84 }
85 sum_length += new_header.payload_length; 85 sum_length += new_header.payload_length;
86 sum_length += 4; // Account for RED header size of 4 bytes. 86 sum_length += 4; // Account for RED header size of 4 bytes.
87 // Store in new list of packets. 87 // Store in new list of packets.
88 new_headers.push_back(new_header); 88 new_headers.push_back(new_header);
89 } 89 }
90 90
91 if (new_headers.size() <= kMaxRedBlocks) { 91 if (new_headers.size() <= kMaxRedBlocks) {
92 // Populate the new packets with payload data. 92 // Populate the new packets with payload data.
93 // |payload_ptr| now points at the first payload byte. 93 // |payload_ptr| now points at the first payload byte.
94 PacketList new_packets; // An empty list to store the split packets in. 94 PacketList new_packets; // An empty list to store the split packets in.
95 for (size_t i = 0; i != new_headers.size(); ++i) { 95 for (size_t i = 0; i != new_headers.size(); ++i) {
96 const auto& new_header = new_headers[i]; 96 const auto& new_header = new_headers[i];
97 size_t payload_length = new_header.payload_length; 97 size_t payload_length = new_header.payload_length;
98 if (payload_ptr + payload_length > 98 if (payload_ptr + payload_length >
99 red_packet->payload.data() + red_packet->payload.size()) { 99 red_packet.payload.data() + red_packet.payload.size()) {
100 // The block lengths in the RED headers do not match the overall 100 // The block lengths in the RED headers do not match the overall
101 // packet length. Something is corrupt. Discard this and the remaining 101 // packet length. Something is corrupt. Discard this and the remaining
102 // payloads from this packet. 102 // payloads from this packet.
103 LOG(LS_WARNING) << "SplitRed length mismatch"; 103 LOG(LS_WARNING) << "SplitRed length mismatch";
104 ret = false; 104 ret = false;
105 break; 105 break;
106 } 106 }
107 107
108 Packet* new_packet = new Packet; 108 Packet new_packet;
109 new_packet->timestamp = new_header.timestamp; 109 new_packet.timestamp = new_header.timestamp;
110 new_packet->payload_type = new_header.payload_type; 110 new_packet.payload_type = new_header.payload_type;
111 new_packet->sequence_number = red_packet->sequence_number; 111 new_packet.sequence_number = red_packet.sequence_number;
112 new_packet->priority.red_level = 112 new_packet.priority.red_level =
113 rtc::checked_cast<int>((new_headers.size() - 1) - i); 113 rtc::checked_cast<int>((new_headers.size() - 1) - i);
114 new_packet->payload.SetData(payload_ptr, payload_length); 114 new_packet.payload.SetData(payload_ptr, payload_length);
115 new_packets.push_front(new_packet); 115 new_packets.push_front(std::move(new_packet));
116 payload_ptr += payload_length; 116 payload_ptr += payload_length;
117 } 117 }
118 // Insert new packets into original list, before the element pointed to by 118 // Insert new packets into original list, before the element pointed to by
119 // iterator |it|. 119 // iterator |it|.
120 packet_list->splice(it, new_packets, new_packets.begin(), 120 packet_list->splice(it, std::move(new_packets));
121 new_packets.end());
122 } else { 121 } else {
123 LOG(LS_WARNING) << "SplitRed too many blocks: " << new_headers.size(); 122 LOG(LS_WARNING) << "SplitRed too many blocks: " << new_headers.size();
124 ret = false; 123 ret = false;
125 } 124 }
126 // Delete old packet payload.
127 delete (*it);
128 // Remove |it| from the packet list. This operation effectively moves the 125 // Remove |it| from the packet list. This operation effectively moves the
129 // iterator |it| to the next packet in the list. Thus, we do not have to 126 // iterator |it| to the next packet in the list. Thus, we do not have to
130 // increment it manually. 127 // increment it manually.
131 it = packet_list->erase(it); 128 it = packet_list->erase(it);
132 } 129 }
133 return ret; 130 return ret;
134 } 131 }
135 132
136 int RedPayloadSplitter::CheckRedPayloads( 133 int RedPayloadSplitter::CheckRedPayloads(
137 PacketList* packet_list, 134 PacketList* packet_list,
138 const DecoderDatabase& decoder_database) { 135 const DecoderDatabase& decoder_database) {
139 PacketList::iterator it = packet_list->begin();
140 int main_payload_type = -1; 136 int main_payload_type = -1;
141 int num_deleted_packets = 0; 137 int num_deleted_packets = 0;
142 while (it != packet_list->end()) { 138 for (auto it = packet_list->begin(); it != packet_list->end(); /* */) {
143 uint8_t this_payload_type = (*it)->payload_type; 139 uint8_t this_payload_type = it->payload_type;
144 if (!decoder_database.IsDtmf(this_payload_type) && 140 if (!decoder_database.IsDtmf(this_payload_type) &&
145 !decoder_database.IsComfortNoise(this_payload_type)) { 141 !decoder_database.IsComfortNoise(this_payload_type)) {
146 if (main_payload_type == -1) { 142 if (main_payload_type == -1) {
147 // This is the first packet in the list which is non-DTMF non-CNG. 143 // This is the first packet in the list which is non-DTMF non-CNG.
148 main_payload_type = this_payload_type; 144 main_payload_type = this_payload_type;
149 } else { 145 } else {
150 if (this_payload_type != main_payload_type) { 146 if (this_payload_type != main_payload_type) {
151 // We do not allow redundant payloads of a different type. 147 // We do not allow redundant payloads of a different type.
152 // Discard this payload.
153 delete (*it);
154 // Remove |it| from the packet list. This operation effectively 148 // Remove |it| from the packet list. This operation effectively
155 // moves the iterator |it| to the next packet in the list. Thus, we 149 // moves the iterator |it| to the next packet in the list. Thus, we
156 // do not have to increment it manually. 150 // do not have to increment it manually.
157 it = packet_list->erase(it); 151 it = packet_list->erase(it);
158 ++num_deleted_packets; 152 ++num_deleted_packets;
159 continue; 153 continue;
160 } 154 }
161 } 155 }
162 } 156 }
163 ++it; 157 ++it;
164 } 158 }
165 return num_deleted_packets; 159 return num_deleted_packets;
166 } 160 }
167 161
168 } // namespace webrtc 162 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698