ACM: Removed the code for InitialDelayManager
It looks to have been unused since the landing of https://codereview.webrtc.org/1419573013 BUG=webrtc:3520 Review-Url: https://codereview.webrtc.org/2363993002 Cr-Commit-Position: refs/heads/master@{#14397}
This commit is contained in:
@ -270,7 +270,6 @@ if (rtc_include_tests) {
|
|||||||
"audio_coding/acm2/audio_coding_module_unittest_oldapi.cc",
|
"audio_coding/acm2/audio_coding_module_unittest_oldapi.cc",
|
||||||
"audio_coding/acm2/call_statistics_unittest.cc",
|
"audio_coding/acm2/call_statistics_unittest.cc",
|
||||||
"audio_coding/acm2/codec_manager_unittest.cc",
|
"audio_coding/acm2/codec_manager_unittest.cc",
|
||||||
"audio_coding/acm2/initial_delay_manager_unittest.cc",
|
|
||||||
"audio_coding/acm2/rent_a_codec_unittest.cc",
|
"audio_coding/acm2/rent_a_codec_unittest.cc",
|
||||||
"audio_coding/codecs/audio_decoder_factory_unittest.cc",
|
"audio_coding/codecs/audio_decoder_factory_unittest.cc",
|
||||||
"audio_coding/codecs/cng/audio_encoder_cng_unittest.cc",
|
"audio_coding/codecs/cng/audio_encoder_cng_unittest.cc",
|
||||||
|
|||||||
@ -92,8 +92,6 @@ rtc_static_library("audio_coding") {
|
|||||||
"acm2/call_statistics.h",
|
"acm2/call_statistics.h",
|
||||||
"acm2/codec_manager.cc",
|
"acm2/codec_manager.cc",
|
||||||
"acm2/codec_manager.h",
|
"acm2/codec_manager.h",
|
||||||
"acm2/initial_delay_manager.cc",
|
|
||||||
"acm2/initial_delay_manager.h",
|
|
||||||
"include/audio_coding_module.h",
|
"include/audio_coding_module.h",
|
||||||
"include/audio_coding_module_typedefs.h",
|
"include/audio_coding_module_typedefs.h",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -24,7 +24,6 @@
|
|||||||
#include "webrtc/engine_configurations.h"
|
#include "webrtc/engine_configurations.h"
|
||||||
#include "webrtc/modules/audio_coding/acm2/acm_resampler.h"
|
#include "webrtc/modules/audio_coding/acm2/acm_resampler.h"
|
||||||
#include "webrtc/modules/audio_coding/acm2/call_statistics.h"
|
#include "webrtc/modules/audio_coding/acm2/call_statistics.h"
|
||||||
#include "webrtc/modules/audio_coding/acm2/initial_delay_manager.h"
|
|
||||||
#include "webrtc/modules/audio_coding/include/audio_coding_module.h"
|
#include "webrtc/modules/audio_coding/include/audio_coding_module.h"
|
||||||
#include "webrtc/modules/audio_coding/neteq/include/neteq.h"
|
#include "webrtc/modules/audio_coding/neteq/include/neteq.h"
|
||||||
#include "webrtc/modules/include/module_common_types.h"
|
#include "webrtc/modules/include/module_common_types.h"
|
||||||
|
|||||||
@ -1,242 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license
|
|
||||||
* that can be found in the LICENSE file in the root of the source
|
|
||||||
* tree. An additional intellectual property rights grant can be found
|
|
||||||
* in the file PATENTS. All contributing project authors may
|
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "webrtc/modules/audio_coding/acm2/initial_delay_manager.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
|
|
||||||
namespace acm2 {
|
|
||||||
|
|
||||||
InitialDelayManager::InitialDelayManager(int initial_delay_ms,
|
|
||||||
int late_packet_threshold)
|
|
||||||
: last_packet_type_(kUndefinedPacket),
|
|
||||||
last_receive_timestamp_(0),
|
|
||||||
timestamp_step_(0),
|
|
||||||
audio_payload_type_(kInvalidPayloadType),
|
|
||||||
initial_delay_ms_(initial_delay_ms),
|
|
||||||
buffered_audio_ms_(0),
|
|
||||||
buffering_(true),
|
|
||||||
playout_timestamp_(0),
|
|
||||||
late_packet_threshold_(late_packet_threshold) {
|
|
||||||
last_packet_rtp_info_.header.payloadType = kInvalidPayloadType;
|
|
||||||
last_packet_rtp_info_.header.ssrc = 0;
|
|
||||||
last_packet_rtp_info_.header.sequenceNumber = 0;
|
|
||||||
last_packet_rtp_info_.header.timestamp = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitialDelayManager::UpdateLastReceivedPacket(
|
|
||||||
const WebRtcRTPHeader& rtp_info,
|
|
||||||
uint32_t receive_timestamp,
|
|
||||||
PacketType type,
|
|
||||||
bool new_codec,
|
|
||||||
int sample_rate_hz,
|
|
||||||
SyncStream* sync_stream) {
|
|
||||||
assert(sync_stream);
|
|
||||||
|
|
||||||
// If payload of audio packets is changing |new_codec| has to be true.
|
|
||||||
assert(!(!new_codec && type == kAudioPacket &&
|
|
||||||
rtp_info.header.payloadType != audio_payload_type_));
|
|
||||||
|
|
||||||
// Just shorthands.
|
|
||||||
const RTPHeader* current_header = &rtp_info.header;
|
|
||||||
RTPHeader* last_header = &last_packet_rtp_info_.header;
|
|
||||||
|
|
||||||
// Don't do anything if getting DTMF. The chance of DTMF in applications where
|
|
||||||
// initial delay is required is very low (we don't know of any). This avoids a
|
|
||||||
// lot of corner cases. The effect of ignoring DTMF packet is minimal. Note
|
|
||||||
// that DTMFs are inserted into NetEq just not accounted here.
|
|
||||||
if (type == kAvtPacket ||
|
|
||||||
(last_packet_type_ != kUndefinedPacket &&
|
|
||||||
!IsNewerSequenceNumber(current_header->sequenceNumber,
|
|
||||||
last_header->sequenceNumber))) {
|
|
||||||
sync_stream->num_sync_packets = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Either if it is a new packet or the first packet record and set variables.
|
|
||||||
if (new_codec ||
|
|
||||||
last_packet_rtp_info_.header.payloadType == kInvalidPayloadType) {
|
|
||||||
timestamp_step_ = 0;
|
|
||||||
if (type == kAudioPacket)
|
|
||||||
audio_payload_type_ = rtp_info.header.payloadType;
|
|
||||||
else
|
|
||||||
audio_payload_type_ = kInvalidPayloadType; // Invalid.
|
|
||||||
|
|
||||||
RecordLastPacket(rtp_info, receive_timestamp, type);
|
|
||||||
sync_stream->num_sync_packets = 0;
|
|
||||||
buffered_audio_ms_ = 0;
|
|
||||||
buffering_ = true;
|
|
||||||
|
|
||||||
// If |buffering_| is set then |playout_timestamp_| should have correct
|
|
||||||
// value.
|
|
||||||
UpdatePlayoutTimestamp(*current_header, sample_rate_hz);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t timestamp_increase = current_header->timestamp -
|
|
||||||
last_header->timestamp;
|
|
||||||
|
|
||||||
// |timestamp_increase| is invalid if this is the first packet. The effect is
|
|
||||||
// that |buffered_audio_ms_| is not increased.
|
|
||||||
if (last_packet_type_ == kUndefinedPacket) {
|
|
||||||
timestamp_increase = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffering_) {
|
|
||||||
buffered_audio_ms_ += timestamp_increase * 1000 / sample_rate_hz;
|
|
||||||
|
|
||||||
// A timestamp that reflects the initial delay, while buffering.
|
|
||||||
UpdatePlayoutTimestamp(*current_header, sample_rate_hz);
|
|
||||||
|
|
||||||
if (buffered_audio_ms_ >= initial_delay_ms_)
|
|
||||||
buffering_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_header->sequenceNumber == last_header->sequenceNumber + 1) {
|
|
||||||
// Two consecutive audio packets, the previous packet-type is audio, so we
|
|
||||||
// can update |timestamp_step_|.
|
|
||||||
if (last_packet_type_ == kAudioPacket)
|
|
||||||
timestamp_step_ = timestamp_increase;
|
|
||||||
RecordLastPacket(rtp_info, receive_timestamp, type);
|
|
||||||
sync_stream->num_sync_packets = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t packet_gap = current_header->sequenceNumber -
|
|
||||||
last_header->sequenceNumber - 1;
|
|
||||||
|
|
||||||
// For smooth transitions leave a gap between audio and sync packets.
|
|
||||||
sync_stream->num_sync_packets = last_packet_type_ == kSyncPacket ?
|
|
||||||
packet_gap - 1 : packet_gap - 2;
|
|
||||||
|
|
||||||
// Do nothing if we haven't received any audio packet.
|
|
||||||
if (sync_stream->num_sync_packets > 0 &&
|
|
||||||
audio_payload_type_ != kInvalidPayloadType) {
|
|
||||||
if (timestamp_step_ == 0) {
|
|
||||||
// Make an estimate for |timestamp_step_| if it is not updated, yet.
|
|
||||||
assert(packet_gap > 0);
|
|
||||||
timestamp_step_ = timestamp_increase / (packet_gap + 1);
|
|
||||||
}
|
|
||||||
sync_stream->timestamp_step = timestamp_step_;
|
|
||||||
|
|
||||||
// Build the first sync-packet based on the current received packet.
|
|
||||||
memcpy(&sync_stream->rtp_info, &rtp_info, sizeof(rtp_info));
|
|
||||||
sync_stream->rtp_info.header.payloadType = audio_payload_type_;
|
|
||||||
|
|
||||||
uint16_t sequence_number_update = sync_stream->num_sync_packets + 1;
|
|
||||||
uint32_t timestamp_update = timestamp_step_ * sequence_number_update;
|
|
||||||
|
|
||||||
// Rewind sequence number and timestamps. This will give a more accurate
|
|
||||||
// description of the missing packets.
|
|
||||||
//
|
|
||||||
// Note that we leave a gap between the last packet in sync-stream and the
|
|
||||||
// current received packet, so it should be compensated for in the following
|
|
||||||
// computation of timestamps and sequence number.
|
|
||||||
sync_stream->rtp_info.header.sequenceNumber -= sequence_number_update;
|
|
||||||
sync_stream->receive_timestamp = receive_timestamp - timestamp_update;
|
|
||||||
sync_stream->rtp_info.header.timestamp -= timestamp_update;
|
|
||||||
sync_stream->rtp_info.header.payloadType = audio_payload_type_;
|
|
||||||
} else {
|
|
||||||
sync_stream->num_sync_packets = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
RecordLastPacket(rtp_info, receive_timestamp, type);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitialDelayManager::RecordLastPacket(const WebRtcRTPHeader& rtp_info,
|
|
||||||
uint32_t receive_timestamp,
|
|
||||||
PacketType type) {
|
|
||||||
last_packet_type_ = type;
|
|
||||||
last_receive_timestamp_ = receive_timestamp;
|
|
||||||
memcpy(&last_packet_rtp_info_, &rtp_info, sizeof(rtp_info));
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitialDelayManager::LatePackets(
|
|
||||||
uint32_t timestamp_now, SyncStream* sync_stream) {
|
|
||||||
assert(sync_stream);
|
|
||||||
sync_stream->num_sync_packets = 0;
|
|
||||||
|
|
||||||
// If there is no estimate of timestamp increment, |timestamp_step_|, then
|
|
||||||
// we cannot estimate the number of late packets.
|
|
||||||
// If the last packet has been CNG, estimating late packets is not meaningful,
|
|
||||||
// as a CNG packet is on unknown length.
|
|
||||||
// We can set a higher threshold if the last packet is CNG and continue
|
|
||||||
// execution, but this is how ACM1 code was written.
|
|
||||||
if (timestamp_step_ <= 0 ||
|
|
||||||
last_packet_type_ == kCngPacket ||
|
|
||||||
last_packet_type_ == kUndefinedPacket ||
|
|
||||||
audio_payload_type_ == kInvalidPayloadType) // No audio packet received.
|
|
||||||
return;
|
|
||||||
|
|
||||||
int num_late_packets = (timestamp_now - last_receive_timestamp_) /
|
|
||||||
timestamp_step_;
|
|
||||||
|
|
||||||
if (num_late_packets < late_packet_threshold_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int sync_offset = 1; // One gap at the end of the sync-stream.
|
|
||||||
if (last_packet_type_ != kSyncPacket) {
|
|
||||||
++sync_offset; // One more gap at the beginning of the sync-stream.
|
|
||||||
--num_late_packets;
|
|
||||||
}
|
|
||||||
uint32_t timestamp_update = sync_offset * timestamp_step_;
|
|
||||||
|
|
||||||
sync_stream->num_sync_packets = num_late_packets;
|
|
||||||
if (num_late_packets == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Build the first sync-packet in the sync-stream.
|
|
||||||
memcpy(&sync_stream->rtp_info, &last_packet_rtp_info_,
|
|
||||||
sizeof(last_packet_rtp_info_));
|
|
||||||
|
|
||||||
// Increase sequence number and timestamps.
|
|
||||||
sync_stream->rtp_info.header.sequenceNumber += sync_offset;
|
|
||||||
sync_stream->rtp_info.header.timestamp += timestamp_update;
|
|
||||||
sync_stream->receive_timestamp = last_receive_timestamp_ + timestamp_update;
|
|
||||||
sync_stream->timestamp_step = timestamp_step_;
|
|
||||||
|
|
||||||
// Sync-packets have audio payload-type.
|
|
||||||
sync_stream->rtp_info.header.payloadType = audio_payload_type_;
|
|
||||||
|
|
||||||
uint16_t sequence_number_update = num_late_packets + sync_offset - 1;
|
|
||||||
timestamp_update = sequence_number_update * timestamp_step_;
|
|
||||||
|
|
||||||
// Fake the last RTP, assuming the caller will inject the whole sync-stream.
|
|
||||||
last_packet_rtp_info_.header.timestamp += timestamp_update;
|
|
||||||
last_packet_rtp_info_.header.sequenceNumber += sequence_number_update;
|
|
||||||
last_packet_rtp_info_.header.payloadType = audio_payload_type_;
|
|
||||||
last_receive_timestamp_ += timestamp_update;
|
|
||||||
|
|
||||||
last_packet_type_ = kSyncPacket;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InitialDelayManager::GetPlayoutTimestamp(uint32_t* playout_timestamp) {
|
|
||||||
if (!buffering_) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*playout_timestamp = playout_timestamp_;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitialDelayManager::DisableBuffering() {
|
|
||||||
buffering_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitialDelayManager::UpdatePlayoutTimestamp(
|
|
||||||
const RTPHeader& current_header, int sample_rate_hz) {
|
|
||||||
playout_timestamp_ = current_header.timestamp - static_cast<uint32_t>(
|
|
||||||
initial_delay_ms_ * sample_rate_hz / 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace acm2
|
|
||||||
|
|
||||||
} // namespace webrtc
|
|
||||||
@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license
|
|
||||||
* that can be found in the LICENSE file in the root of the source
|
|
||||||
* tree. An additional intellectual property rights grant can be found
|
|
||||||
* in the file PATENTS. All contributing project authors may
|
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef WEBRTC_MODULES_AUDIO_CODING_ACM2_INITIAL_DELAY_MANAGER_H_
|
|
||||||
#define WEBRTC_MODULES_AUDIO_CODING_ACM2_INITIAL_DELAY_MANAGER_H_
|
|
||||||
|
|
||||||
#include "webrtc/modules/include/module_common_types.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
|
|
||||||
namespace acm2 {
|
|
||||||
|
|
||||||
class InitialDelayManager {
|
|
||||||
public:
|
|
||||||
enum PacketType {
|
|
||||||
kUndefinedPacket, kCngPacket, kAvtPacket, kAudioPacket, kSyncPacket };
|
|
||||||
|
|
||||||
// Specifies a stream of sync-packets.
|
|
||||||
struct SyncStream {
|
|
||||||
SyncStream()
|
|
||||||
: num_sync_packets(0),
|
|
||||||
receive_timestamp(0),
|
|
||||||
timestamp_step(0) {
|
|
||||||
memset(&rtp_info, 0, sizeof(rtp_info));
|
|
||||||
}
|
|
||||||
|
|
||||||
int num_sync_packets;
|
|
||||||
|
|
||||||
// RTP header of the first sync-packet in the sequence.
|
|
||||||
WebRtcRTPHeader rtp_info;
|
|
||||||
|
|
||||||
// Received timestamp of the first sync-packet in the sequence.
|
|
||||||
uint32_t receive_timestamp;
|
|
||||||
|
|
||||||
// Samples per packet.
|
|
||||||
uint32_t timestamp_step;
|
|
||||||
};
|
|
||||||
|
|
||||||
InitialDelayManager(int initial_delay_ms, int late_packet_threshold);
|
|
||||||
|
|
||||||
// Update with the last received RTP header, |header|, and received timestamp,
|
|
||||||
// |received_timestamp|. |type| indicates the packet type. If codec is changed
|
|
||||||
// since the last time |new_codec| should be true. |sample_rate_hz| is the
|
|
||||||
// decoder's sampling rate in Hz. |header| has a field to store sampling rate
|
|
||||||
// but we are not sure if that is properly set at the send side, and |header|
|
|
||||||
// is declared constant in the caller of this function
|
|
||||||
// (AcmReceiver::InsertPacket()). |sync_stream| contains information required
|
|
||||||
// to generate a stream of sync packets.
|
|
||||||
void UpdateLastReceivedPacket(const WebRtcRTPHeader& header,
|
|
||||||
uint32_t receive_timestamp,
|
|
||||||
PacketType type,
|
|
||||||
bool new_codec,
|
|
||||||
int sample_rate_hz,
|
|
||||||
SyncStream* sync_stream);
|
|
||||||
|
|
||||||
// Based on the last received timestamp and given the current timestamp,
|
|
||||||
// sequence of late (or perhaps missing) packets is computed.
|
|
||||||
void LatePackets(uint32_t timestamp_now, SyncStream* sync_stream);
|
|
||||||
|
|
||||||
// Get playout timestamp.
|
|
||||||
// Returns true if the timestamp is valid (when buffering), otherwise false.
|
|
||||||
bool GetPlayoutTimestamp(uint32_t* playout_timestamp);
|
|
||||||
|
|
||||||
// True if buffered audio is less than the given initial delay (specified at
|
|
||||||
// the constructor). Buffering might be disabled by the client of this class.
|
|
||||||
bool buffering() { return buffering_; }
|
|
||||||
|
|
||||||
// Disable buffering in the class.
|
|
||||||
void DisableBuffering();
|
|
||||||
|
|
||||||
// True if any packet received for buffering.
|
|
||||||
bool PacketBuffered() { return last_packet_type_ != kUndefinedPacket; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
static const uint8_t kInvalidPayloadType = 0xFF;
|
|
||||||
|
|
||||||
// Update playout timestamps. While buffering, this is about
|
|
||||||
// |initial_delay_ms| millisecond behind the latest received timestamp.
|
|
||||||
void UpdatePlayoutTimestamp(const RTPHeader& current_header,
|
|
||||||
int sample_rate_hz);
|
|
||||||
|
|
||||||
// Record an RTP headr and related parameter
|
|
||||||
void RecordLastPacket(const WebRtcRTPHeader& rtp_info,
|
|
||||||
uint32_t receive_timestamp,
|
|
||||||
PacketType type);
|
|
||||||
|
|
||||||
PacketType last_packet_type_;
|
|
||||||
WebRtcRTPHeader last_packet_rtp_info_;
|
|
||||||
uint32_t last_receive_timestamp_;
|
|
||||||
uint32_t timestamp_step_;
|
|
||||||
uint8_t audio_payload_type_;
|
|
||||||
const int initial_delay_ms_;
|
|
||||||
int buffered_audio_ms_;
|
|
||||||
bool buffering_;
|
|
||||||
|
|
||||||
// During the initial phase where packets are being accumulated and silence
|
|
||||||
// is played out, |playout_ts| is a timestamp which is equal to
|
|
||||||
// |initial_delay_ms_| milliseconds earlier than the most recently received
|
|
||||||
// RTP timestamp.
|
|
||||||
uint32_t playout_timestamp_;
|
|
||||||
|
|
||||||
// If the number of late packets exceed this value (computed based on current
|
|
||||||
// timestamp and last received timestamp), sequence of sync-packets is
|
|
||||||
// specified.
|
|
||||||
const int late_packet_threshold_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace acm2
|
|
||||||
|
|
||||||
} // namespace webrtc
|
|
||||||
|
|
||||||
#endif // WEBRTC_MODULES_AUDIO_CODING_ACM2_INITIAL_DELAY_MANAGER_H_
|
|
||||||
@ -1,378 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license
|
|
||||||
* that can be found in the LICENSE file in the root of the source
|
|
||||||
* tree. An additional intellectual property rights grant can be found
|
|
||||||
* in the file PATENTS. All contributing project authors may
|
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
|
||||||
#include "webrtc/modules/audio_coding/acm2/initial_delay_manager.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
|
|
||||||
namespace acm2 {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
const uint8_t kAudioPayloadType = 0;
|
|
||||||
const uint8_t kCngPayloadType = 1;
|
|
||||||
const uint8_t kAvtPayloadType = 2;
|
|
||||||
|
|
||||||
const int kSamplingRateHz = 16000;
|
|
||||||
const int kInitDelayMs = 200;
|
|
||||||
const int kFrameSizeMs = 20;
|
|
||||||
const uint32_t kTimestampStep = kFrameSizeMs * kSamplingRateHz / 1000;
|
|
||||||
const int kLatePacketThreshold = 5;
|
|
||||||
|
|
||||||
void InitRtpInfo(WebRtcRTPHeader* rtp_info) {
|
|
||||||
memset(rtp_info, 0, sizeof(*rtp_info));
|
|
||||||
rtp_info->header.markerBit = false;
|
|
||||||
rtp_info->header.payloadType = kAudioPayloadType;
|
|
||||||
rtp_info->header.sequenceNumber = 1234;
|
|
||||||
rtp_info->header.timestamp = 0xFFFFFFFD; // Close to wrap around.
|
|
||||||
rtp_info->header.ssrc = 0x87654321; // Arbitrary.
|
|
||||||
rtp_info->header.numCSRCs = 0; // Arbitrary.
|
|
||||||
rtp_info->header.paddingLength = 0;
|
|
||||||
rtp_info->header.headerLength = sizeof(RTPHeader);
|
|
||||||
rtp_info->header.payload_type_frequency = kSamplingRateHz;
|
|
||||||
rtp_info->header.extension.absoluteSendTime = 0;
|
|
||||||
rtp_info->header.extension.transmissionTimeOffset = 0;
|
|
||||||
rtp_info->frameType = kAudioFrameSpeech;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ForwardRtpHeader(int n,
|
|
||||||
WebRtcRTPHeader* rtp_info,
|
|
||||||
uint32_t* rtp_receive_timestamp) {
|
|
||||||
rtp_info->header.sequenceNumber += n;
|
|
||||||
rtp_info->header.timestamp += n * kTimestampStep;
|
|
||||||
*rtp_receive_timestamp += n * kTimestampStep;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NextRtpHeader(WebRtcRTPHeader* rtp_info,
|
|
||||||
uint32_t* rtp_receive_timestamp) {
|
|
||||||
ForwardRtpHeader(1, rtp_info, rtp_receive_timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
class InitialDelayManagerTest : public ::testing::Test {
|
|
||||||
protected:
|
|
||||||
InitialDelayManagerTest()
|
|
||||||
: manager_(new InitialDelayManager(kInitDelayMs, kLatePacketThreshold)),
|
|
||||||
rtp_receive_timestamp_(1111) { } // Arbitrary starting point.
|
|
||||||
|
|
||||||
virtual void SetUp() {
|
|
||||||
ASSERT_TRUE(manager_.get() != NULL);
|
|
||||||
InitRtpInfo(&rtp_info_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetNextRtpHeader(WebRtcRTPHeader* rtp_info,
|
|
||||||
uint32_t* rtp_receive_timestamp) const {
|
|
||||||
memcpy(rtp_info, &rtp_info_, sizeof(*rtp_info));
|
|
||||||
*rtp_receive_timestamp = rtp_receive_timestamp_;
|
|
||||||
NextRtpHeader(rtp_info, rtp_receive_timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<InitialDelayManager> manager_;
|
|
||||||
WebRtcRTPHeader rtp_info_;
|
|
||||||
uint32_t rtp_receive_timestamp_;
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_F(InitialDelayManagerTest, Init) {
|
|
||||||
EXPECT_TRUE(manager_->buffering());
|
|
||||||
EXPECT_FALSE(manager_->PacketBuffered());
|
|
||||||
manager_->DisableBuffering();
|
|
||||||
EXPECT_FALSE(manager_->buffering());
|
|
||||||
InitialDelayManager::SyncStream sync_stream;
|
|
||||||
|
|
||||||
// Call before any packet inserted.
|
|
||||||
manager_->LatePackets(0x6789ABCD, &sync_stream); // Arbitrary but large
|
|
||||||
// receive timestamp.
|
|
||||||
EXPECT_EQ(0, sync_stream.num_sync_packets);
|
|
||||||
|
|
||||||
// Insert non-audio packets, a CNG and DTMF.
|
|
||||||
rtp_info_.header.payloadType = kCngPayloadType;
|
|
||||||
manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
|
|
||||||
InitialDelayManager::kCngPacket, false,
|
|
||||||
kSamplingRateHz, &sync_stream);
|
|
||||||
EXPECT_EQ(0, sync_stream.num_sync_packets);
|
|
||||||
ForwardRtpHeader(5, &rtp_info_, &rtp_receive_timestamp_);
|
|
||||||
rtp_info_.header.payloadType = kAvtPayloadType;
|
|
||||||
manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
|
|
||||||
InitialDelayManager::kAvtPacket, false,
|
|
||||||
kSamplingRateHz, &sync_stream);
|
|
||||||
// Gap in sequence numbers but no audio received, sync-stream should be empty.
|
|
||||||
EXPECT_EQ(0, sync_stream.num_sync_packets);
|
|
||||||
manager_->LatePackets(0x45678987, &sync_stream); // Large arbitrary receive
|
|
||||||
// timestamp.
|
|
||||||
// |manager_| has no estimate of timestamp-step and has not received any
|
|
||||||
// audio packet.
|
|
||||||
EXPECT_EQ(0, sync_stream.num_sync_packets);
|
|
||||||
|
|
||||||
|
|
||||||
NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
|
|
||||||
rtp_info_.header.payloadType = kAudioPayloadType;
|
|
||||||
// First packet.
|
|
||||||
manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
|
|
||||||
InitialDelayManager::kAudioPacket, true,
|
|
||||||
kSamplingRateHz, &sync_stream);
|
|
||||||
EXPECT_EQ(0, sync_stream.num_sync_packets);
|
|
||||||
|
|
||||||
// Call LatePAcket() after only one packet inserted.
|
|
||||||
manager_->LatePackets(0x6789ABCD, &sync_stream); // Arbitrary but large
|
|
||||||
// receive timestamp.
|
|
||||||
EXPECT_EQ(0, sync_stream.num_sync_packets);
|
|
||||||
|
|
||||||
// Gap in timestamp, but this packet is also flagged as "new," therefore,
|
|
||||||
// expecting empty sync-stream.
|
|
||||||
ForwardRtpHeader(5, &rtp_info_, &rtp_receive_timestamp_);
|
|
||||||
manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
|
|
||||||
InitialDelayManager::kAudioPacket, true,
|
|
||||||
kSamplingRateHz, &sync_stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(InitialDelayManagerTest, MissingPacket) {
|
|
||||||
InitialDelayManager::SyncStream sync_stream;
|
|
||||||
// First packet.
|
|
||||||
manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
|
|
||||||
InitialDelayManager::kAudioPacket, true,
|
|
||||||
kSamplingRateHz, &sync_stream);
|
|
||||||
ASSERT_EQ(0, sync_stream.num_sync_packets);
|
|
||||||
|
|
||||||
// Second packet.
|
|
||||||
NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
|
|
||||||
manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
|
|
||||||
InitialDelayManager::kAudioPacket, false,
|
|
||||||
kSamplingRateHz, &sync_stream);
|
|
||||||
ASSERT_EQ(0, sync_stream.num_sync_packets);
|
|
||||||
|
|
||||||
// Third packet, missing packets start from here.
|
|
||||||
NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
|
|
||||||
|
|
||||||
// First sync-packet in sync-stream is one after the above packet.
|
|
||||||
WebRtcRTPHeader expected_rtp_info;
|
|
||||||
uint32_t expected_receive_timestamp;
|
|
||||||
GetNextRtpHeader(&expected_rtp_info, &expected_receive_timestamp);
|
|
||||||
|
|
||||||
const int kNumMissingPackets = 10;
|
|
||||||
ForwardRtpHeader(kNumMissingPackets, &rtp_info_, &rtp_receive_timestamp_);
|
|
||||||
manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
|
|
||||||
InitialDelayManager::kAudioPacket, false,
|
|
||||||
kSamplingRateHz, &sync_stream);
|
|
||||||
EXPECT_EQ(kNumMissingPackets - 2, sync_stream.num_sync_packets);
|
|
||||||
EXPECT_EQ(0, memcmp(&expected_rtp_info, &sync_stream.rtp_info,
|
|
||||||
sizeof(expected_rtp_info)));
|
|
||||||
EXPECT_EQ(kTimestampStep, sync_stream.timestamp_step);
|
|
||||||
EXPECT_EQ(expected_receive_timestamp, sync_stream.receive_timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// There hasn't been any consecutive packets to estimate timestamp-step.
|
|
||||||
TEST_F(InitialDelayManagerTest, MissingPacketEstimateTimestamp) {
|
|
||||||
InitialDelayManager::SyncStream sync_stream;
|
|
||||||
// First packet.
|
|
||||||
manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
|
|
||||||
InitialDelayManager::kAudioPacket, true,
|
|
||||||
kSamplingRateHz, &sync_stream);
|
|
||||||
ASSERT_EQ(0, sync_stream.num_sync_packets);
|
|
||||||
|
|
||||||
// Second packet, missing packets start here.
|
|
||||||
NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
|
|
||||||
|
|
||||||
// First sync-packet in sync-stream is one after the above.
|
|
||||||
WebRtcRTPHeader expected_rtp_info;
|
|
||||||
uint32_t expected_receive_timestamp;
|
|
||||||
GetNextRtpHeader(&expected_rtp_info, &expected_receive_timestamp);
|
|
||||||
|
|
||||||
const int kNumMissingPackets = 10;
|
|
||||||
ForwardRtpHeader(kNumMissingPackets, &rtp_info_, &rtp_receive_timestamp_);
|
|
||||||
manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
|
|
||||||
InitialDelayManager::kAudioPacket, false,
|
|
||||||
kSamplingRateHz, &sync_stream);
|
|
||||||
EXPECT_EQ(kNumMissingPackets - 2, sync_stream.num_sync_packets);
|
|
||||||
EXPECT_EQ(0, memcmp(&expected_rtp_info, &sync_stream.rtp_info,
|
|
||||||
sizeof(expected_rtp_info)));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(InitialDelayManagerTest, MissingPacketWithCng) {
|
|
||||||
InitialDelayManager::SyncStream sync_stream;
|
|
||||||
|
|
||||||
// First packet.
|
|
||||||
manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
|
|
||||||
InitialDelayManager::kAudioPacket, true,
|
|
||||||
kSamplingRateHz, &sync_stream);
|
|
||||||
ASSERT_EQ(0, sync_stream.num_sync_packets);
|
|
||||||
|
|
||||||
// Second packet as CNG.
|
|
||||||
NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
|
|
||||||
rtp_info_.header.payloadType = kCngPayloadType;
|
|
||||||
manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
|
|
||||||
InitialDelayManager::kCngPacket, false,
|
|
||||||
kSamplingRateHz, &sync_stream);
|
|
||||||
ASSERT_EQ(0, sync_stream.num_sync_packets);
|
|
||||||
|
|
||||||
// Audio packet after CNG. Missing packets start from this packet.
|
|
||||||
rtp_info_.header.payloadType = kAudioPayloadType;
|
|
||||||
NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
|
|
||||||
|
|
||||||
// Timestamps are increased higher than regular packet.
|
|
||||||
const uint32_t kCngTimestampStep = 5 * kTimestampStep;
|
|
||||||
rtp_info_.header.timestamp += kCngTimestampStep;
|
|
||||||
rtp_receive_timestamp_ += kCngTimestampStep;
|
|
||||||
|
|
||||||
// First sync-packet in sync-stream is the one after the above packet.
|
|
||||||
WebRtcRTPHeader expected_rtp_info;
|
|
||||||
uint32_t expected_receive_timestamp;
|
|
||||||
GetNextRtpHeader(&expected_rtp_info, &expected_receive_timestamp);
|
|
||||||
|
|
||||||
const int kNumMissingPackets = 10;
|
|
||||||
ForwardRtpHeader(kNumMissingPackets, &rtp_info_, &rtp_receive_timestamp_);
|
|
||||||
manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
|
|
||||||
InitialDelayManager::kAudioPacket, false,
|
|
||||||
kSamplingRateHz, &sync_stream);
|
|
||||||
EXPECT_EQ(kNumMissingPackets - 2, sync_stream.num_sync_packets);
|
|
||||||
EXPECT_EQ(0, memcmp(&expected_rtp_info, &sync_stream.rtp_info,
|
|
||||||
sizeof(expected_rtp_info)));
|
|
||||||
EXPECT_EQ(kTimestampStep, sync_stream.timestamp_step);
|
|
||||||
EXPECT_EQ(expected_receive_timestamp, sync_stream.receive_timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(InitialDelayManagerTest, LatePacket) {
|
|
||||||
InitialDelayManager::SyncStream sync_stream;
|
|
||||||
// First packet.
|
|
||||||
manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
|
|
||||||
InitialDelayManager::kAudioPacket, true,
|
|
||||||
kSamplingRateHz, &sync_stream);
|
|
||||||
ASSERT_EQ(0, sync_stream.num_sync_packets);
|
|
||||||
|
|
||||||
// Second packet.
|
|
||||||
NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
|
|
||||||
manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
|
|
||||||
InitialDelayManager::kAudioPacket, false,
|
|
||||||
kSamplingRateHz, &sync_stream);
|
|
||||||
ASSERT_EQ(0, sync_stream.num_sync_packets);
|
|
||||||
|
|
||||||
// Timestamp increment for 10ms;
|
|
||||||
const uint32_t kTimestampStep10Ms = kSamplingRateHz / 100;
|
|
||||||
|
|
||||||
// 10 ms after the second packet is inserted.
|
|
||||||
uint32_t timestamp_now = rtp_receive_timestamp_ + kTimestampStep10Ms;
|
|
||||||
|
|
||||||
// Third packet, late packets start from this packet.
|
|
||||||
NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
|
|
||||||
|
|
||||||
// First sync-packet in sync-stream, which is one after the above packet.
|
|
||||||
WebRtcRTPHeader expected_rtp_info;
|
|
||||||
uint32_t expected_receive_timestamp;
|
|
||||||
GetNextRtpHeader(&expected_rtp_info, &expected_receive_timestamp);
|
|
||||||
|
|
||||||
const int kLatePacketThreshold = 5;
|
|
||||||
|
|
||||||
int expected_num_late_packets = kLatePacketThreshold - 1;
|
|
||||||
for (int k = 0; k < 2; ++k) {
|
|
||||||
for (int n = 1; n < kLatePacketThreshold * kFrameSizeMs / 10; ++n) {
|
|
||||||
manager_->LatePackets(timestamp_now, &sync_stream);
|
|
||||||
EXPECT_EQ(0, sync_stream.num_sync_packets) <<
|
|
||||||
"try " << k << " loop number " << n;
|
|
||||||
timestamp_now += kTimestampStep10Ms;
|
|
||||||
}
|
|
||||||
manager_->LatePackets(timestamp_now, &sync_stream);
|
|
||||||
|
|
||||||
EXPECT_EQ(expected_num_late_packets, sync_stream.num_sync_packets) <<
|
|
||||||
"try " << k;
|
|
||||||
EXPECT_EQ(kTimestampStep, sync_stream.timestamp_step) <<
|
|
||||||
"try " << k;
|
|
||||||
EXPECT_EQ(expected_receive_timestamp, sync_stream.receive_timestamp) <<
|
|
||||||
"try " << k;
|
|
||||||
EXPECT_EQ(0, memcmp(&expected_rtp_info, &sync_stream.rtp_info,
|
|
||||||
sizeof(expected_rtp_info)));
|
|
||||||
|
|
||||||
timestamp_now += kTimestampStep10Ms;
|
|
||||||
|
|
||||||
// |manger_| assumes the |sync_stream| obtained by LatePacket() is fully
|
|
||||||
// injected. The last injected packet is sync-packet, therefore, there will
|
|
||||||
// not be any gap between sync stream of this and the next iteration.
|
|
||||||
ForwardRtpHeader(sync_stream.num_sync_packets, &expected_rtp_info,
|
|
||||||
&expected_receive_timestamp);
|
|
||||||
expected_num_late_packets = kLatePacketThreshold;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test "no-gap" for missing packet after late packet.
|
|
||||||
// |expected_rtp_info| is the expected sync-packet if any packet is missing.
|
|
||||||
memcpy(&rtp_info_, &expected_rtp_info, sizeof(rtp_info_));
|
|
||||||
rtp_receive_timestamp_ = expected_receive_timestamp;
|
|
||||||
|
|
||||||
int kNumMissingPackets = 3; // Arbitrary.
|
|
||||||
ForwardRtpHeader(kNumMissingPackets, &rtp_info_, &rtp_receive_timestamp_);
|
|
||||||
manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
|
|
||||||
InitialDelayManager::kAudioPacket, false,
|
|
||||||
kSamplingRateHz, &sync_stream);
|
|
||||||
|
|
||||||
// Note that there is one packet gap between the last sync-packet and the
|
|
||||||
// latest inserted packet.
|
|
||||||
EXPECT_EQ(kNumMissingPackets - 1, sync_stream.num_sync_packets);
|
|
||||||
EXPECT_EQ(kTimestampStep, sync_stream.timestamp_step);
|
|
||||||
EXPECT_EQ(expected_receive_timestamp, sync_stream.receive_timestamp);
|
|
||||||
EXPECT_EQ(0, memcmp(&expected_rtp_info, &sync_stream.rtp_info,
|
|
||||||
sizeof(expected_rtp_info)));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(InitialDelayManagerTest, NoLatePacketAfterCng) {
|
|
||||||
InitialDelayManager::SyncStream sync_stream;
|
|
||||||
|
|
||||||
// First packet.
|
|
||||||
manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
|
|
||||||
InitialDelayManager::kAudioPacket, true,
|
|
||||||
kSamplingRateHz, &sync_stream);
|
|
||||||
ASSERT_EQ(0, sync_stream.num_sync_packets);
|
|
||||||
|
|
||||||
// Second packet as CNG.
|
|
||||||
NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
|
|
||||||
rtp_info_.header.payloadType = kCngPayloadType;
|
|
||||||
manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
|
|
||||||
InitialDelayManager::kCngPacket, false,
|
|
||||||
kSamplingRateHz, &sync_stream);
|
|
||||||
ASSERT_EQ(0, sync_stream.num_sync_packets);
|
|
||||||
|
|
||||||
// Forward the time more then |kLatePacketThreshold| packets.
|
|
||||||
uint32_t timestamp_now = rtp_receive_timestamp_ + kTimestampStep * (3 +
|
|
||||||
kLatePacketThreshold);
|
|
||||||
|
|
||||||
manager_->LatePackets(timestamp_now, &sync_stream);
|
|
||||||
EXPECT_EQ(0, sync_stream.num_sync_packets);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(InitialDelayManagerTest, BufferingAudio) {
|
|
||||||
InitialDelayManager::SyncStream sync_stream;
|
|
||||||
|
|
||||||
// Very first packet is not counted in calculation of buffered audio.
|
|
||||||
for (int n = 0; n < kInitDelayMs / kFrameSizeMs; ++n) {
|
|
||||||
manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
|
|
||||||
InitialDelayManager::kAudioPacket,
|
|
||||||
n == 0, kSamplingRateHz, &sync_stream);
|
|
||||||
EXPECT_EQ(0, sync_stream.num_sync_packets);
|
|
||||||
EXPECT_TRUE(manager_->buffering());
|
|
||||||
const uint32_t expected_playout_timestamp = rtp_info_.header.timestamp -
|
|
||||||
kInitDelayMs * kSamplingRateHz / 1000;
|
|
||||||
uint32_t actual_playout_timestamp = 0;
|
|
||||||
EXPECT_TRUE(manager_->GetPlayoutTimestamp(&actual_playout_timestamp));
|
|
||||||
EXPECT_EQ(expected_playout_timestamp, actual_playout_timestamp);
|
|
||||||
NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
|
|
||||||
InitialDelayManager::kAudioPacket,
|
|
||||||
false, kSamplingRateHz, &sync_stream);
|
|
||||||
EXPECT_EQ(0, sync_stream.num_sync_packets);
|
|
||||||
EXPECT_FALSE(manager_->buffering());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace acm2
|
|
||||||
|
|
||||||
} // namespace webrtc
|
|
||||||
@ -180,8 +180,6 @@
|
|||||||
'acm2/call_statistics.h',
|
'acm2/call_statistics.h',
|
||||||
'acm2/codec_manager.cc',
|
'acm2/codec_manager.cc',
|
||||||
'acm2/codec_manager.h',
|
'acm2/codec_manager.h',
|
||||||
'acm2/initial_delay_manager.cc',
|
|
||||||
'acm2/initial_delay_manager.h',
|
|
||||||
'include/audio_coding_module.h',
|
'include/audio_coding_module.h',
|
||||||
'include/audio_coding_module_typedefs.h',
|
'include/audio_coding_module_typedefs.h',
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user