| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |