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 9c4f5809068f8964ef74882c0414f184ce37eef0..8d5d5d41c8a5e19a843b496a1537cb3a83221b4b 100644 |
--- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc |
+++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc |
@@ -330,8 +330,7 @@ int NetEqImpl::CurrentDelayMs() const { |
// Sum up the samples in the packet buffer with the future length of the sync |
// buffer, and divide the sum by the sample rate. |
const size_t delay_samples = |
- packet_buffer_->NumSamplesInBuffer(decoder_database_.get(), |
- decoder_frame_length_) + |
+ packet_buffer_->NumSamplesInBuffer(decoder_frame_length_) + |
sync_buffer_->FutureLength(); |
// The division below will truncate. |
const int delay_ms = |
@@ -376,8 +375,7 @@ int NetEqImpl::NetworkStatistics(NetEqNetworkStatistics* stats) { |
rtc::CritScope lock(&crit_sect_); |
assert(decoder_database_.get()); |
const size_t total_samples_in_buffers = |
- packet_buffer_->NumSamplesInBuffer(decoder_database_.get(), |
- decoder_frame_length_) + |
+ packet_buffer_->NumSamplesInBuffer(decoder_frame_length_) + |
sync_buffer_->FutureLength(); |
assert(delay_manager_.get()); |
assert(decision_logic_.get()); |
@@ -662,29 +660,71 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header, |
receive_timestamp); |
} |
+ PacketList parsed_packet_list; |
+ while (!packet_list.empty()) { |
+ std::unique_ptr<Packet> packet(packet_list.front()); |
+ packet_list.pop_front(); |
+ const DecoderDatabase::DecoderInfo* info = |
+ decoder_database_->GetDecoderInfo(packet->header.payloadType); |
+ if (!info) { |
+ LOG(LS_WARNING) << "SplitAudio unknown payload type"; |
+ return kUnknownRtpPayloadType; |
+ } |
+ |
+ if (info->IsComfortNoise()) { |
+ // Carry comfort noise packets along. |
+ parsed_packet_list.push_back(packet.release()); |
+ } else { |
+ std::vector<AudioDecoder::ParseResult> results = |
+ info->GetDecoder()->ParsePayload( |
+ &packet->payload, packet->header.timestamp, packet->primary); |
+ |
+ // Reuse the packet if possible |
+ if (results.size() == 1) { |
+ auto& result = results[0]; |
+ RTC_DCHECK(result.frame); |
+ packet->header.timestamp = result.timestamp; |
+ packet->primary = result.primary; |
+ packet->frame = std::move(result.frame); |
+ parsed_packet_list.push_back(packet.release()); |
+ } else { |
+ for (auto& result : results) { |
+ // If you can't parse, return an empty list instead! |
kwiberg-webrtc
2016/09/15 12:00:59
Not sure I understand this comment.
ossu
2016/09/15 13:07:55
Me neither.
|
+ RTC_DCHECK(result.frame); |
+ std::unique_ptr<Packet> parsed_packet(new Packet); |
+ parsed_packet->header = packet->header; |
+ parsed_packet->header.timestamp = result.timestamp; |
+ // TODO(ossu): Move from primary to some sort of priority level. |
+ parsed_packet->primary = result.primary; |
+ parsed_packet->frame = std::move(result.frame); |
+ parsed_packet_list.push_back(parsed_packet.release()); |
+ } |
+ } |
kwiberg-webrtc
2016/09/15 12:00:59
Can you eliminate the special case? E.g. by checki
ossu
2016/09/15 13:07:55
Acknowledged.
|
+ } |
+ } |
+ |
if (nack_enabled_) { |
RTC_DCHECK(nack_); |
if (update_sample_rate_and_channels) { |
nack_->Reset(); |
} |
- nack_->UpdateLastReceivedPacket(packet_list.front()->header.sequenceNumber, |
- packet_list.front()->header.timestamp); |
+ nack_->UpdateLastReceivedPacket( |
+ parsed_packet_list.front()->header.sequenceNumber, |
+ parsed_packet_list.front()->header.timestamp); |
} |
// Insert packets in buffer. |
const size_t buffer_length_before_insert = |
packet_buffer_->NumPacketsInBuffer(); |
ret = packet_buffer_->InsertPacketList( |
- &packet_list, |
- *decoder_database_, |
- ¤t_rtp_payload_type_, |
+ &parsed_packet_list, *decoder_database_, ¤t_rtp_payload_type_, |
¤t_cng_rtp_payload_type_); |
if (ret == PacketBuffer::kFlushed) { |
// Reset DSP timestamp etc. if packet buffer flushed. |
new_codec_ = true; |
update_sample_rate_and_channels = true; |
} else if (ret != PacketBuffer::kOK) { |
- PacketBuffer::DeleteAllPackets(&packet_list); |
+ PacketBuffer::DeleteAllPackets(&parsed_packet_list); |
return kOtherError; |
} |
@@ -1421,31 +1461,24 @@ int NetEqImpl::DecodeLoop(PacketList* packet_list, const Operations& operation, |
operation == kFastAccelerate || operation == kMerge || |
operation == kPreemptiveExpand); |
packet_list->pop_front(); |
- const size_t payload_length = packet->payload.size(); |
- int decode_length; |
- if (!packet->primary) { |
- // This is a redundant payload; call the special decoder method. |
- decode_length = decoder->DecodeRedundant( |
- packet->payload.data(), packet->payload.size(), fs_hz_, |
- (decoded_buffer_length_ - *decoded_length) * sizeof(int16_t), |
- &decoded_buffer_[*decoded_length], speech_type); |
- } else { |
- decode_length = decoder->Decode( |
- packet->payload.data(), packet->payload.size(), fs_hz_, |
- (decoded_buffer_length_ - *decoded_length) * sizeof(int16_t), |
- &decoded_buffer_[*decoded_length], speech_type); |
- } |
- |
+ auto opt_result = packet->frame->Decode( |
+ rtc::ArrayView<int16_t>(&decoded_buffer_[*decoded_length], |
+ decoded_buffer_length_ - *decoded_length)); |
delete packet; |
packet = NULL; |
- if (decode_length > 0) { |
- *decoded_length += decode_length; |
- // Update |decoder_frame_length_| with number of samples per channel. |
- decoder_frame_length_ = |
- static_cast<size_t>(decode_length) / decoder->Channels(); |
- } else if (decode_length < 0) { |
+ if (opt_result) { |
+ const auto& result = *opt_result; |
+ *speech_type = result.speech_type; |
+ if (result.num_decoded_samples > 0) { |
+ *decoded_length += result.num_decoded_samples; |
+ // Update |decoder_frame_length_| with number of samples per channel. |
+ decoder_frame_length_ = |
+ result.num_decoded_samples / decoder->Channels(); |
+ } |
+ } else { |
// Error. |
- LOG(LS_WARNING) << "Decode " << decode_length << " " << payload_length; |
+ // TODO(ossu): What to put here? |
+ LOG(LS_WARNING) << "Decode error"; |
*decoded_length = -1; |
PacketBuffer::DeleteAllPackets(packet_list); |
break; |
@@ -1908,7 +1941,7 @@ int NetEqImpl::ExtractPackets(size_t required_samples, |
} |
stats_.PacketsDiscarded(discard_count); |
stats_.StoreWaitingTime(packet->waiting_time->ElapsedMs()); |
- assert(!packet->payload.empty()); |
+ RTC_DCHECK(!packet->empty()); |
packet_list->push_back(packet); // Store packet in list. |
if (first_packet) { |
@@ -1925,27 +1958,24 @@ int NetEqImpl::ExtractPackets(size_t required_samples, |
} |
// Store number of extracted samples. |
- int packet_duration = 0; |
- AudioDecoder* decoder = decoder_database_->GetDecoder( |
- packet->header.payloadType); |
- if (decoder) { |
- if (packet->primary) { |
- packet_duration = decoder->PacketDuration(packet->payload.data(), |
- packet->payload.size()); |
- } else { |
- packet_duration = decoder->PacketDurationRedundant( |
- packet->payload.data(), packet->payload.size()); |
+ size_t packet_duration = 0; |
+ if (packet->frame) { |
+ packet_duration = packet->frame->Duration(); |
+ // TODO(ossu): Is this the correct way to track samples decoded from a |
+ // redundant packet? |
+ if (packet_duration > 0 && !packet->primary) { |
stats_.SecondaryDecodedSamples(packet_duration); |
} |
} else if (!decoder_database_->IsComfortNoise(packet->header.payloadType)) { |
LOG(LS_WARNING) << "Unknown payload type " |
<< static_cast<int>(packet->header.payloadType); |
- assert(false); |
+ RTC_NOTREACHED(); |
} |
- if (packet_duration <= 0) { |
+ |
+ if (packet_duration == 0) { |
// Decoder did not return a packet duration. Assume that the packet |
// contains the same number of samples as the previous one. |
- packet_duration = rtc::checked_cast<int>(decoder_frame_length_); |
+ packet_duration = decoder_frame_length_; |
} |
extracted_samples = packet->header.timestamp - first_timestamp + |
packet_duration; |