| 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..d62d44f2b4a08dd8635d3c0ffc105f75c6cc023e 100644
|
| --- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc
|
| +++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc
|
| @@ -14,6 +14,7 @@
|
| #include <memory.h> // memset
|
|
|
| #include <algorithm>
|
| +#include <utility>
|
| #include <vector>
|
|
|
| #include "webrtc/base/checks.h"
|
| @@ -282,6 +283,7 @@ int NetEqImpl::RemovePayloadType(uint8_t rtp_payload_type) {
|
| rtc::CritScope lock(&crit_sect_);
|
| int ret = decoder_database_->Remove(rtp_payload_type);
|
| if (ret == DecoderDatabase::kOK) {
|
| + packet_buffer_->DiscardPacketsWithPayloadType(rtp_payload_type);
|
| return kOK;
|
| } else if (ret == DecoderDatabase::kDecoderNotFound) {
|
| error_code_ = kDecoderNotFound;
|
| @@ -330,8 +332,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 +377,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 +662,64 @@ 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(std::move(packet->payload),
|
| + packet->header.timestamp,
|
| + packet->primary);
|
| + const RTPHeader& original_header = packet->header;
|
| + for (auto& result : results) {
|
| + RTC_DCHECK(result.frame);
|
| + // Reuse the packet if possible
|
| + if (!packet) {
|
| + packet.reset(new Packet);
|
| + packet->header = original_header;
|
| + }
|
| + packet->header.timestamp = result.timestamp;
|
| + // TODO(ossu): Move from primary to some sort of priority level.
|
| + packet->primary = result.primary;
|
| + packet->frame = std::move(result.frame);
|
| + parsed_packet_list.push_back(packet.release());
|
| + }
|
| + }
|
| + }
|
| +
|
| 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,36 +1456,29 @@ 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 += rtc::checked_cast<int>(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;
|
| }
|
| - if (*decoded_length > static_cast<int>(decoded_buffer_length_)) {
|
| + if (*decoded_length > rtc::checked_cast<int>(decoded_buffer_length_)) {
|
| // Guard against overflow.
|
| LOG(LS_WARNING) << "Decoded too much.";
|
| PacketBuffer::DeleteAllPackets(packet_list);
|
| @@ -1892,7 +1920,7 @@ int NetEqImpl::ExtractPackets(size_t required_samples,
|
| return -1;
|
| }
|
| uint32_t first_timestamp = header->timestamp;
|
| - int extracted_samples = 0;
|
| + size_t extracted_samples = 0;
|
|
|
| // Packet extraction loop.
|
| do {
|
| @@ -1908,7 +1936,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 +1953,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());
|
| - stats_.SecondaryDecodedSamples(packet_duration);
|
| + 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(rtc::checked_cast<int>(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;
|
| @@ -1964,8 +1989,7 @@ int NetEqImpl::ExtractPackets(size_t required_samples,
|
| }
|
| prev_sequence_number = header->sequenceNumber;
|
| }
|
| - } while (extracted_samples < rtc::checked_cast<int>(required_samples) &&
|
| - next_packet_available);
|
| + } while (extracted_samples < required_samples && next_packet_available);
|
|
|
| if (extracted_samples > 0) {
|
| // Delete old packets only when we are going to decode something. Otherwise,
|
| @@ -1975,7 +1999,7 @@ int NetEqImpl::ExtractPackets(size_t required_samples,
|
| packet_buffer_->DiscardAllOldPackets(timestamp_);
|
| }
|
|
|
| - return extracted_samples;
|
| + return rtc::checked_cast<int>(extracted_samples);
|
| }
|
|
|
| void NetEqImpl::UpdatePlcComponents(int fs_hz, size_t channels) {
|
|
|