Index: webrtc/modules/audio_coding/neteq/neteq_impl.cc |
diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.cc b/webrtc/modules/audio_coding/neteq/neteq_impl.cc |
index 8439c5c971a8d45704e80c6c8b457a1f5452b5c1..00e3c5824417a772efad8467657f8fd30d247e7d 100644 |
--- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc |
+++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc |
@@ -581,21 +581,18 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header, |
} |
PacketList packet_list; |
- { |
+ // Insert packet in a packet list. |
+ packet_list.push_back([&rtp_header, &payload] { |
// Convert to Packet. |
- // Create |packet| within this separate scope, since it should not be used |
- // directly once it's been inserted in the packet list. This way, |packet| |
- // is not defined outside of this block. |
- Packet* packet = new Packet; |
- packet->payload_type = rtp_header.header.payloadType; |
- packet->sequence_number = rtp_header.header.sequenceNumber; |
- packet->timestamp = rtp_header.header.timestamp; |
- packet->payload.SetData(payload.data(), payload.size()); |
+ Packet packet; |
+ packet.payload_type = rtp_header.header.payloadType; |
+ packet.sequence_number = rtp_header.header.sequenceNumber; |
+ packet.timestamp = rtp_header.header.timestamp; |
+ packet.payload.SetData(payload.data(), payload.size()); |
// Waiting time will be set upon inserting the packet in the buffer. |
- RTC_DCHECK(!packet->waiting_time); |
- // Insert packet in a packet list. |
- packet_list.push_back(packet); |
- } |
+ RTC_DCHECK(!packet.waiting_time); |
+ return packet; |
+ }()); |
bool update_sample_rate_and_channels = false; |
// Reinitialize NetEq if it's needed (changed SSRC or first call). |
@@ -641,7 +638,6 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header, |
// Check for RED payload type, and separate payloads into several packets. |
if (decoder_database_->IsRed(rtp_header.header.payloadType)) { |
if (!red_payload_splitter_->SplitRed(&packet_list)) { |
- PacketBuffer::DeleteAllPackets(&packet_list); |
return kRedundancySplitError; |
} |
// Only accept a few RED payloads of the same type as the main data, |
@@ -652,16 +648,15 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header, |
// Check payload types. |
if (decoder_database_->CheckPayloadTypes(packet_list) == |
DecoderDatabase::kDecoderNotFound) { |
- PacketBuffer::DeleteAllPackets(&packet_list); |
return kUnknownRtpPayloadType; |
} |
RTC_DCHECK(!packet_list.empty()); |
// Store these for later use, since the first packet may very well disappear |
// before we need these values. |
- const uint32_t main_timestamp = packet_list.front()->timestamp; |
- const uint8_t main_payload_type = packet_list.front()->payload_type; |
- const uint16_t main_sequence_number = packet_list.front()->sequence_number; |
+ const uint32_t main_timestamp = packet_list.front().timestamp; |
+ const uint8_t main_payload_type = packet_list.front().payload_type; |
+ const uint16_t main_sequence_number = packet_list.front().sequence_number; |
// Scale timestamp to internal domain (only for some codecs). |
timestamp_scaler_->ToInternal(&packet_list); |
@@ -670,23 +665,19 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header, |
// DTMF payloads found. |
PacketList::iterator it = packet_list.begin(); |
while (it != packet_list.end()) { |
- Packet* current_packet = (*it); |
- assert(current_packet); |
- assert(!current_packet->payload.empty()); |
- if (decoder_database_->IsDtmf(current_packet->payload_type)) { |
+ Packet& current_packet = (*it); |
hlundin-webrtc
2016/10/21 13:53:33
const Packet&
ossu
2016/10/24 12:18:28
Done.
|
+ RTC_DCHECK(!current_packet.payload.empty()); |
+ if (decoder_database_->IsDtmf(current_packet.payload_type)) { |
DtmfEvent event; |
- int ret = DtmfBuffer::ParseEvent(current_packet->timestamp, |
- current_packet->payload.data(), |
- current_packet->payload.size(), &event); |
+ int ret = DtmfBuffer::ParseEvent(current_packet.timestamp, |
+ current_packet.payload.data(), |
+ current_packet.payload.size(), &event); |
if (ret != DtmfBuffer::kOK) { |
- PacketBuffer::DeleteAllPackets(&packet_list); |
return kDtmfParsingError; |
} |
if (dtmf_buffer_->InsertEvent(event) != DtmfBuffer::kOK) { |
- PacketBuffer::DeleteAllPackets(&packet_list); |
return kDtmfInsertError; |
} |
- delete current_packet; |
it = packet_list.erase(it); |
} else { |
++it; |
@@ -700,19 +691,18 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header, |
AudioDecoder* decoder = decoder_database_->GetDecoder(main_payload_type); |
RTC_DCHECK(decoder); // Should always get a valid object, since we have |
// already checked that the payload types are known. |
- decoder->IncomingPacket(packet_list.front()->payload.data(), |
- packet_list.front()->payload.size(), |
- packet_list.front()->sequence_number, |
- packet_list.front()->timestamp, |
+ decoder->IncomingPacket(packet_list.front().payload.data(), |
+ packet_list.front().payload.size(), |
+ packet_list.front().sequence_number, |
+ packet_list.front().timestamp, |
receive_timestamp); |
} |
PacketList parsed_packet_list; |
while (!packet_list.empty()) { |
- std::unique_ptr<Packet> packet(packet_list.front()); |
- packet_list.pop_front(); |
+ Packet& packet = packet_list.front(); |
const DecoderDatabase::DecoderInfo* info = |
- decoder_database_->GetDecoderInfo(packet->payload_type); |
+ decoder_database_->GetDecoderInfo(packet.payload_type); |
if (!info) { |
LOG(LS_WARNING) << "SplitAudio unknown payload type"; |
return kUnknownRtpPayloadType; |
@@ -720,28 +710,43 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header, |
if (info->IsComfortNoise()) { |
// Carry comfort noise packets along. |
- parsed_packet_list.push_back(packet.release()); |
+ parsed_packet_list.splice(parsed_packet_list.end(), packet_list, |
+ packet_list.begin()); |
} else { |
+ const auto sequence_number = packet.sequence_number; |
+ const auto payload_type = packet.payload_type; |
+ const Packet::Priority original_priority = packet.priority; |
+ auto packet_from_result = [&] (AudioDecoder::ParseResult& result) { |
+ Packet new_packet; |
+ new_packet.sequence_number = sequence_number; |
+ new_packet.payload_type = payload_type; |
+ new_packet.timestamp = result.timestamp; |
+ new_packet.priority.codec_level = result.priority; |
+ new_packet.priority.red_level = original_priority.red_level; |
+ new_packet.frame = std::move(result.frame); |
+ return new_packet; |
+ }; |
+ |
std::vector<AudioDecoder::ParseResult> results = |
- info->GetDecoder()->ParsePayload(std::move(packet->payload), |
- packet->timestamp); |
- const auto sequence_number = packet->sequence_number; |
- const auto payload_type = packet->payload_type; |
- const Packet::Priority original_priority = packet->priority; |
- for (auto& result : results) { |
- RTC_DCHECK(result.frame); |
- // Reuse the packet if possible. |
- if (!packet) { |
- packet.reset(new Packet); |
- packet->sequence_number = sequence_number; |
- packet->payload_type = payload_type; |
+ info->GetDecoder()->ParsePayload(std::move(packet.payload), |
+ packet.timestamp); |
+ if (results.empty()) { |
+ packet_list.pop_front(); |
+ } else { |
+ bool first = true; |
+ for (auto& result : results) { |
+ RTC_DCHECK(result.frame); |
+ RTC_DCHECK_GE(result.priority, 0); |
+ if (first) { |
+ // Re-use the node and move it to parsed_packet_list. |
+ packet_list.front() = packet_from_result(result); |
+ parsed_packet_list.splice(parsed_packet_list.end(), packet_list, |
+ packet_list.begin()); |
+ first = false; |
+ } else { |
+ parsed_packet_list.push_back(packet_from_result(result)); |
+ } |
} |
- packet->timestamp = result.timestamp; |
- RTC_DCHECK_GE(result.priority, 0); |
- packet->priority.codec_level = result.priority; |
- packet->priority.red_level = original_priority.red_level; |
- packet->frame = std::move(result.frame); |
- parsed_packet_list.push_back(packet.release()); |
} |
} |
} |
@@ -757,7 +762,6 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header, |
new_codec_ = true; |
update_sample_rate_and_channels = true; |
} else if (ret != PacketBuffer::kOK) { |
- PacketBuffer::DeleteAllPackets(&parsed_packet_list); |
return kOtherError; |
} |
@@ -1344,15 +1348,15 @@ int NetEqImpl::Decode(PacketList* packet_list, Operations* operation, |
AudioDecoder* decoder = decoder_database_->GetActiveDecoder(); |
if (!packet_list->empty()) { |
- const Packet* packet = packet_list->front(); |
- uint8_t payload_type = packet->payload_type; |
+ const Packet& packet = packet_list->front(); |
+ uint8_t payload_type = packet.payload_type; |
if (!decoder_database_->IsComfortNoise(payload_type)) { |
decoder = decoder_database_->GetDecoder(payload_type); |
assert(decoder); |
if (!decoder) { |
LOG(LS_WARNING) << "Unknown payload type " |
<< static_cast<int>(payload_type); |
- PacketBuffer::DeleteAllPackets(packet_list); |
+ packet_list->clear(); |
return kDecoderNotFound; |
} |
bool decoder_changed; |
@@ -1365,7 +1369,7 @@ int NetEqImpl::Decode(PacketList* packet_list, Operations* operation, |
if (!decoder_info) { |
LOG(LS_WARNING) << "Unknown payload type " |
<< static_cast<int>(payload_type); |
- PacketBuffer::DeleteAllPackets(packet_list); |
+ packet_list->clear(); |
return kDecoderNotFound; |
} |
// If sampling rate or number of channels has changed, we need to make |
@@ -1475,13 +1479,10 @@ int NetEqImpl::DecodeCng(AudioDecoder* decoder, int* decoded_length, |
int NetEqImpl::DecodeLoop(PacketList* packet_list, const Operations& operation, |
AudioDecoder* decoder, int* decoded_length, |
AudioDecoder::SpeechType* speech_type) { |
- Packet* packet = NULL; |
- if (!packet_list->empty()) { |
- packet = packet_list->front(); |
- } |
- |
// Do decoding. |
- while (packet && !decoder_database_->IsComfortNoise(packet->payload_type)) { |
+ while ( |
+ !packet_list->empty() && |
+ !decoder_database_->IsComfortNoise(packet_list->front().payload_type)) { |
assert(decoder); // At this point, we must have a decoder object. |
// The number of channels in the |sync_buffer_| should be the same as the |
// number decoder channels. |
@@ -1490,12 +1491,11 @@ int NetEqImpl::DecodeLoop(PacketList* packet_list, const Operations& operation, |
assert(operation == kNormal || operation == kAccelerate || |
operation == kFastAccelerate || operation == kMerge || |
operation == kPreemptiveExpand); |
- packet_list->pop_front(); |
- auto opt_result = packet->frame->Decode( |
+ |
+ auto opt_result = packet_list->front().frame->Decode( |
rtc::ArrayView<int16_t>(&decoded_buffer_[*decoded_length], |
decoded_buffer_length_ - *decoded_length)); |
- delete packet; |
- packet = NULL; |
+ packet_list->pop_front(); |
if (opt_result) { |
const auto& result = *opt_result; |
*speech_type = result.speech_type; |
@@ -1510,27 +1510,23 @@ int NetEqImpl::DecodeLoop(PacketList* packet_list, const Operations& operation, |
// TODO(ossu): What to put here? |
LOG(LS_WARNING) << "Decode error"; |
*decoded_length = -1; |
- PacketBuffer::DeleteAllPackets(packet_list); |
+ packet_list->clear(); |
break; |
} |
if (*decoded_length > rtc::checked_cast<int>(decoded_buffer_length_)) { |
// Guard against overflow. |
LOG(LS_WARNING) << "Decoded too much."; |
- PacketBuffer::DeleteAllPackets(packet_list); |
+ packet_list->clear(); |
return kDecodedTooMuch; |
} |
- if (!packet_list->empty()) { |
- packet = packet_list->front(); |
- } else { |
- packet = NULL; |
- } |
} // End of decode loop. |
// If the list is not empty at this point, either a decoding error terminated |
// the while-loop, or list must hold exactly one CNG packet. |
- assert(packet_list->empty() || *decoded_length < 0 || |
- (packet_list->size() == 1 && packet && |
- decoder_database_->IsComfortNoise(packet->payload_type))); |
+ assert( |
+ packet_list->empty() || *decoded_length < 0 || |
+ (packet_list->size() == 1 && |
+ decoder_database_->IsComfortNoise(packet_list->front().payload_type))); |
return 0; |
} |
@@ -1770,13 +1766,11 @@ int NetEqImpl::DoRfc3389Cng(PacketList* packet_list, bool play_dtmf) { |
if (!packet_list->empty()) { |
// Must have exactly one SID frame at this point. |
assert(packet_list->size() == 1); |
- Packet* packet = packet_list->front(); |
- packet_list->pop_front(); |
- if (!decoder_database_->IsComfortNoise(packet->payload_type)) { |
+ const Packet& packet = packet_list->front(); |
+ if (!decoder_database_->IsComfortNoise(packet.payload_type)) { |
LOG(LS_ERROR) << "Trying to decode non-CNG payload as CNG."; |
return kOtherError; |
} |
- // UpdateParameters() deletes |packet|. |
if (comfort_noise_->UpdateParameters(packet) == |
ComfortNoise::kInternalError) { |
algorithm_buffer_->Zeros(output_size_samples_); |
@@ -1960,19 +1954,16 @@ int NetEqImpl::ExtractPackets(size_t required_samples, |
// Packet extraction loop. |
do { |
timestamp_ = next_packet->timestamp; |
- size_t discard_count = 0; |
- Packet* packet = packet_buffer_->GetNextPacket(&discard_count); |
+ rtc::Optional<Packet> packet = packet_buffer_->GetNextPacket(); |
// |next_packet| may be invalid after the |packet_buffer_| operation. |
- next_packet = NULL; |
+ next_packet = nullptr; |
if (!packet) { |
LOG(LS_ERROR) << "Should always be able to extract a packet here"; |
assert(false); // Should always be able to extract a packet here. |
return -1; |
} |
- stats_.PacketsDiscarded(discard_count); |
stats_.StoreWaitingTime(packet->waiting_time->ElapsedMs()); |
RTC_DCHECK(!packet->empty()); |
- packet_list->push_back(packet); // Store packet in list. |
if (first_packet) { |
first_packet = false; |
@@ -2008,6 +1999,9 @@ int NetEqImpl::ExtractPackets(size_t required_samples, |
} |
extracted_samples = packet->timestamp - first_timestamp + packet_duration; |
+ packet_list->push_back(std::move(*packet)); // Store packet in list. |
+ packet = rtc::Optional<Packet>(); // Ensure it's never used after the move. |
+ |
// Check what packet is available next. |
next_packet = packet_buffer_->PeekNextPacket(); |
next_packet_available = false; |