#include <algorithm>
#include <vector>
+#include "webrtc/common.h"
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
+#include "webrtc/experiments.h"
#include "webrtc/modules/pacing/include/paced_sender.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
RtcpIntraFrameObserver* intra_frame_observer,
RtcpBandwidthObserver* bandwidth_observer,
RemoteBitrateEstimator* remote_bitrate_estimator,
- RtcpRttObserver* rtt_observer,
+ RtcpRttStats* rtt_stats,
PacedSender* paced_sender,
RtpRtcp* default_rtp_rtcp,
bool sender)
rtp_observer_(NULL),
rtcp_observer_(NULL),
intra_frame_observer_(intra_frame_observer),
- rtt_observer_(rtt_observer),
+ rtt_stats_(rtt_stats),
paced_sender_(paced_sender),
bandwidth_observer_(bandwidth_observer),
send_timestamp_extension_id_(kInvalidRtpExtensionId),
absolute_send_time_extension_id_(kInvalidRtpExtensionId),
- receive_absolute_send_time_enabled_(false),
external_transport_(NULL),
decoder_reset_(true),
wait_for_key_frame_(false),
decode_thread_(NULL),
- external_encryption_(NULL),
effect_filter_(NULL),
color_enhancement_(false),
mtu_(0),
sender_(sender),
nack_history_size_sender_(kSendSidePacketHistorySize),
max_nack_reordering_threshold_(kMaxPacketAgeToNack),
- pre_render_callback_(NULL) {
+ pre_render_callback_(NULL),
+ config_(config) {
WEBRTC_TRACE(kTraceMemory, kTraceVideo, ViEId(engine_id, channel_id),
"ViEChannel::ViEChannel(channel_id: %d, engine_id: %d)",
channel_id, engine_id);
configuration.rtcp_feedback = this;
configuration.intra_frame_callback = intra_frame_observer;
configuration.bandwidth_callback = bandwidth_observer;
- configuration.rtt_observer = rtt_observer;
+ configuration.rtt_stats = rtt_stats;
configuration.remote_bitrate_estimator = remote_bitrate_estimator;
configuration.paced_sender = paced_sender;
configuration.receive_statistics = vie_receiver_.GetReceiveStatistics();
configuration.outgoing_transport = &vie_sender_;
configuration.intra_frame_callback = intra_frame_observer_;
configuration.bandwidth_callback = bandwidth_observer_.get();
- configuration.rtt_observer = rtt_observer_;
+ configuration.rtt_stats = rtt_stats_;
configuration.paced_sender = paced_sender_;
RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration);
rtp_rtcp->SetGenericFECStatus(fec_enabled, payload_type_red,
payload_type_fec);
}
+ rtp_rtcp->SetSendingStatus(rtp_rtcp_->Sending());
rtp_rtcp->SetSendingMediaStatus(rtp_rtcp_->SendingMedia());
simulcast_rtp_rtcp_.push_back(rtp_rtcp);
}
module_process_thread_.DeRegisterModule(rtp_rtcp);
rtp_rtcp->SetSendingStatus(false);
rtp_rtcp->SetSendingMediaStatus(false);
+ rtp_rtcp->RegisterSendFrameCountObserver(NULL);
+ rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(NULL);
+ rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(NULL);
+ rtp_rtcp->RegisterVideoBitrateObserver(NULL);
simulcast_rtp_rtcp_.pop_back();
removed_rtp_rtcp_.push_front(rtp_rtcp);
}
rtp_rtcp->DeregisterSendRtpHeaderExtension(
kRtpExtensionAbsoluteSendTime);
}
+ rtp_rtcp->RegisterSendFrameCountObserver(
+ rtp_rtcp_->GetSendFrameCountObserver());
+ rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(
+ rtp_rtcp_->GetSendChannelRtcpStatisticsCallback());
+ rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(
+ rtp_rtcp_->GetSendChannelRtpStatisticsCallback());
+ rtp_rtcp->RegisterVideoBitrateObserver(
+ rtp_rtcp_->GetVideoBitrateObserver());
}
// |RegisterSimulcastRtpRtcpModules| resets all old weak pointers and old
// modules can be deleted after this step.
module_process_thread_.DeRegisterModule(rtp_rtcp);
rtp_rtcp->SetSendingStatus(false);
rtp_rtcp->SetSendingMediaStatus(false);
+ rtp_rtcp->RegisterSendFrameCountObserver(NULL);
+ rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(NULL);
+ rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(NULL);
+ rtp_rtcp->RegisterVideoBitrateObserver(NULL);
simulcast_rtp_rtcp_.pop_back();
removed_rtp_rtcp_.push_front(rtp_rtcp);
}
}
int ViEChannel::SetReceiveAbsoluteSendTimeStatus(bool enable, int id) {
- receive_absolute_send_time_enabled_ = enable;
return vie_receiver_.SetReceiveAbsoluteSendTimeStatus(enable, id) ? 0 : -1;
}
-bool ViEChannel::GetReceiveAbsoluteSendTimeStatus() const {
- return receive_absolute_send_time_enabled_;
+void ViEChannel::SetRtcpXrRrtrStatus(bool enable) {
+ CriticalSectionScoped cs(rtp_rtcp_cs_.get());
+ rtp_rtcp_->SetRtcpXrRrtrStatus(enable);
}
void ViEChannel::SetTransmissionSmoothingStatus(bool enable) {
ViEId(engine_id_, channel_id_),
"%s(usage:%d, SSRC: 0x%x, idx:%u)",
__FUNCTION__, usage, SSRC, simulcast_idx);
+ int rtx_settings = kRtxRetransmitted;
+ if (config_.Get<PaddingStrategy>().redundant_payloads)
+ rtx_settings |= kRtxRedundantPayloads;
if (simulcast_idx == 0) {
if (usage == kViEStreamTypeRtx) {
- return rtp_rtcp_->SetRTXSendStatus(kRtxRetransmitted, true, SSRC);
+ return rtp_rtcp_->SetRTXSendStatus(rtx_settings, true, SSRC);
}
return rtp_rtcp_->SetSSRC(SSRC);
}
}
RtpRtcp* rtp_rtcp_module = *it;
if (usage == kViEStreamTypeRtx) {
- return rtp_rtcp_module->SetRTXSendStatus(kRtxRetransmitted, true, SSRC);
+ return rtp_rtcp_module->SetRTXSendStatus(rtx_settings, true, SSRC);
}
return rtp_rtcp_module->SetSSRC(SSRC);
}
return 0;
}
+void ViEChannel::RegisterSendChannelRtcpStatisticsCallback(
+ RtcpStatisticsCallback* callback) {
+ WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
+ __FUNCTION__);
+ rtp_rtcp_->RegisterSendChannelRtcpStatisticsCallback(callback);
+ CriticalSectionScoped cs(rtp_rtcp_cs_.get());
+ for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
+ it != simulcast_rtp_rtcp_.end();
+ ++it) {
+ (*it)->RegisterSendChannelRtcpStatisticsCallback(callback);
+ }
+}
+
// TODO(holmer): This is a bad function name as it implies that it returns the
// received RTCP, while it actually returns the statistics which will be sent
// in the RTCP.
"%s", __FUNCTION__);
uint32_t remote_ssrc = vie_receiver_.GetRemoteSsrc();
- uint8_t frac_lost = 0;
StreamStatistician* statistician =
vie_receiver_.GetReceiveStatistics()->GetStatistician(remote_ssrc);
- StreamStatistician::Statistics receive_stats;
+ RtcpStatistics receive_stats;
if (!statistician || !statistician->GetStatistics(
&receive_stats, rtp_rtcp_->RTCP() == kRtcpOff)) {
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
*cumulative_lost = receive_stats.cumulative_lost;
*extended_max = receive_stats.extended_max_sequence_number;
*jitter_samples = receive_stats.jitter;
- *fraction_lost = frac_lost;
uint16_t dummy = 0;
uint16_t rtt = 0;
return 0;
}
+void ViEChannel::RegisterReceiveChannelRtcpStatisticsCallback(
+ RtcpStatisticsCallback* callback) {
+ WEBRTC_TRACE(kTraceInfo,
+ kTraceVideo,
+ ViEId(engine_id_, channel_id_),
+ "%s",
+ __FUNCTION__);
+ vie_receiver_.GetReceiveStatistics()->RegisterRtcpStatisticsCallback(
+ callback);
+}
+
int32_t ViEChannel::GetRtpStatistics(uint32_t* bytes_sent,
uint32_t* packets_sent,
uint32_t* bytes_received,
return 0;
}
+void ViEChannel::RegisterSendChannelRtpStatisticsCallback(
+ StreamDataCountersCallback* callback) {
+ WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
+ __FUNCTION__);
+ rtp_rtcp_->RegisterSendChannelRtpStatisticsCallback(callback);
+ {
+ CriticalSectionScoped cs(rtp_rtcp_cs_.get());
+ for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
+ it != simulcast_rtp_rtcp_.end();
+ it++) {
+ (*it)->RegisterSendChannelRtpStatisticsCallback(callback);
+ }
+ }
+}
+
+void ViEChannel::RegisterReceiveChannelRtpStatisticsCallback(
+ StreamDataCountersCallback* callback) {
+ WEBRTC_TRACE(kTraceInfo,
+ kTraceVideo,
+ ViEId(engine_id_, channel_id_),
+ "%s",
+ __FUNCTION__);
+ vie_receiver_.GetReceiveStatistics()->RegisterRtpStatisticsCallback(callback);
+}
+
void ViEChannel::GetBandwidthUsage(uint32_t* total_bitrate_sent,
uint32_t* video_bitrate_sent,
uint32_t* fec_bitrate_sent,
}
}
+bool ViEChannel::GetSendSideDelay(int* avg_send_delay,
+ int* max_send_delay) const {
+ WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
+ __FUNCTION__);
+
+ *avg_send_delay = 0;
+ *max_send_delay = 0;
+ bool valid_estimate = false;
+ int num_send_delays = 0;
+ if (rtp_rtcp_->GetSendSideDelay(avg_send_delay, max_send_delay)) {
+ ++num_send_delays;
+ valid_estimate = true;
+ }
+ CriticalSectionScoped cs(rtp_rtcp_cs_.get());
+ for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
+ it != simulcast_rtp_rtcp_.end(); it++) {
+ RtpRtcp* rtp_rtcp = *it;
+ int sub_stream_avg_delay = 0;
+ int sub_stream_max_delay = 0;
+ if (rtp_rtcp->GetSendSideDelay(&sub_stream_avg_delay,
+ &sub_stream_max_delay)) {
+ *avg_send_delay += sub_stream_avg_delay;
+ *max_send_delay = std::max(*max_send_delay, sub_stream_max_delay);
+ ++num_send_delays;
+ }
+ }
+ if (num_send_delays > 0) {
+ valid_estimate = true;
+ *avg_send_delay = *avg_send_delay / num_send_delays;
+ *avg_send_delay = (*avg_send_delay + num_send_delays / 2) / num_send_delays;
+ }
+ return valid_estimate;
+}
+
+void ViEChannel::RegisterSendBitrateObserver(
+ BitrateStatisticsObserver* observer) {
+ rtp_rtcp_->RegisterVideoBitrateObserver(observer);
+ CriticalSectionScoped cs(rtp_rtcp_cs_.get());
+ for (std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
+ it != simulcast_rtp_rtcp_.end();
+ it++) {
+ (*it)->RegisterVideoBitrateObserver(observer);
+ }
+}
+
void ViEChannel::GetEstimatedReceiveBandwidth(
uint32_t* estimated_bandwidth) const {
vie_receiver_.EstimatedReceiveBandwidth(estimated_bandwidth);
}
+void ViEChannel::GetReceiveBandwidthEstimatorStats(
+ ReceiveBandwidthEstimatorStats* output) const {
+ vie_receiver_.GetReceiveBandwidthEstimatorStats(output);
+}
+
int32_t ViEChannel::StartRTPDump(const char file_nameUTF8[1024],
RTPDirections direction) {
WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
}
int32_t ViEChannel::ReceivedRTPPacket(
- const void* rtp_packet, const int32_t rtp_packet_length) {
+ const void* rtp_packet, const int32_t rtp_packet_length,
+ const PacketTime& packet_time) {
{
CriticalSectionScoped cs(callback_cs_.get());
if (!external_transport_) {
return -1;
}
}
- return vie_receiver_.ReceivedRTPPacket(rtp_packet, rtp_packet_length);
+ return vie_receiver_.ReceivedRTPPacket(
+ rtp_packet, rtp_packet_length, packet_time);
}
int32_t ViEChannel::ReceivedRTCPPacket(
return 0;
}
-int32_t ViEChannel::RegisterExternalEncryption(Encryption* encryption) {
- WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
- __FUNCTION__);
-
- CriticalSectionScoped cs(callback_cs_.get());
- if (external_encryption_) {
- WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
- "%s: external encryption already registered", __FUNCTION__);
- return -1;
- }
-
- external_encryption_ = encryption;
-
- vie_receiver_.RegisterExternalDecryption(encryption);
- vie_sender_.RegisterExternalEncryption(encryption);
-
- WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
- "%s", "external encryption object registerd with channel=%d",
- channel_id_);
- return 0;
-}
-
-int32_t ViEChannel::DeRegisterExternalEncryption() {
- WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
- __FUNCTION__);
-
- CriticalSectionScoped cs(callback_cs_.get());
- if (!external_encryption_) {
- WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
- "%s: external encryption is not registered", __FUNCTION__);
- return -1;
- }
-
- external_transport_ = NULL;
- vie_receiver_.DeregisterExternalDecryption();
- vie_sender_.DeregisterExternalEncryption();
- WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
- "%s external encryption object de-registerd with channel=%d",
- __FUNCTION__, channel_id_);
- return 0;
-}
-
int32_t ViEChannel::SetVoiceChannel(int32_t ve_channel_id,
VoEVideoSync* ve_sync_interface) {
WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
pre_render_callback_ = pre_render_callback;
}
+void ViEChannel::RegisterPreDecodeImageCallback(
+ EncodedImageCallback* pre_decode_callback) {
+ CriticalSectionScoped cs(callback_cs_.get());
+ vcm_.RegisterPreDecodeImageCallback(pre_decode_callback);
+}
+
void ViEChannel::OnApplicationDataReceived(const int32_t id,
const uint8_t sub_type,
const uint32_t name,
statistician->ResetStatistics();
}
+void ViEChannel::RegisterSendFrameCountObserver(
+ FrameCountObserver* observer) {
+ rtp_rtcp_->RegisterSendFrameCountObserver(observer);
+ CriticalSectionScoped cs(rtp_rtcp_cs_.get());
+ for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
+ it != simulcast_rtp_rtcp_.end();
+ it++) {
+ (*it)->RegisterSendFrameCountObserver(observer);
+ }
+}
+
} // namespace webrtc