/* * Copyright (c) 2012 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/video_engine/vie_rtp_rtcp_impl.h" #include "webrtc/engine_configurations.h" #include "webrtc/system_wrappers/interface/file_wrapper.h" #include "webrtc/system_wrappers/interface/logging.h" #include "webrtc/video_engine/include/vie_errors.h" #include "webrtc/video_engine/vie_channel.h" #include "webrtc/video_engine/vie_channel_manager.h" #include "webrtc/video_engine/vie_defines.h" #include "webrtc/video_engine/vie_encoder.h" #include "webrtc/video_engine/vie_impl.h" #include "webrtc/video_engine/vie_shared_data.h" namespace webrtc { // Helper methods for converting between module format and ViE API format. static RTCPMethod ViERTCPModeToRTCPMethod(ViERTCPMode api_mode) { switch (api_mode) { case kRtcpNone: return kRtcpOff; case kRtcpCompound_RFC4585: return kRtcpCompound; case kRtcpNonCompound_RFC5506: return kRtcpNonCompound; } assert(false); return kRtcpOff; } static ViERTCPMode RTCPMethodToViERTCPMode(RTCPMethod module_method) { switch (module_method) { case kRtcpOff: return kRtcpNone; case kRtcpCompound: return kRtcpCompound_RFC4585; case kRtcpNonCompound: return kRtcpNonCompound_RFC5506; } assert(false); return kRtcpNone; } static KeyFrameRequestMethod APIRequestToModuleRequest( ViEKeyFrameRequestMethod api_method) { switch (api_method) { case kViEKeyFrameRequestNone: return kKeyFrameReqFirRtp; case kViEKeyFrameRequestPliRtcp: return kKeyFrameReqPliRtcp; case kViEKeyFrameRequestFirRtp: return kKeyFrameReqFirRtp; case kViEKeyFrameRequestFirRtcp: return kKeyFrameReqFirRtcp; } assert(false); return kKeyFrameReqFirRtp; } ViERTP_RTCP* ViERTP_RTCP::GetInterface(VideoEngine* video_engine) { #ifdef WEBRTC_VIDEO_ENGINE_RTP_RTCP_API if (!video_engine) { return NULL; } VideoEngineImpl* vie_impl = static_cast(video_engine); ViERTP_RTCPImpl* vie_rtpimpl = vie_impl; // Increase ref count. (*vie_rtpimpl)++; return vie_rtpimpl; #else return NULL; #endif } int ViERTP_RTCPImpl::Release() { // Decrease ref count. (*this)--; int32_t ref_count = GetCount(); if (ref_count < 0) { LOG(LS_ERROR) << "ViERTP_RTCP released too many times."; shared_data_->SetLastError(kViEAPIDoesNotExist); return -1; } return ref_count; } ViERTP_RTCPImpl::ViERTP_RTCPImpl(ViESharedData* shared_data) : shared_data_(shared_data) {} ViERTP_RTCPImpl::~ViERTP_RTCPImpl() {} int ViERTP_RTCPImpl::SetLocalSSRC(const int video_channel, const unsigned int SSRC, const StreamType usage, const unsigned char simulcast_idx) { LOG_F(LS_INFO) << "channel: " << video_channel << " ssrc: " << SSRC << ""; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->SetSSRC(SSRC, usage, simulcast_idx) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::SetRemoteSSRCType(const int videoChannel, const StreamType usage, const unsigned int SSRC) const { LOG_F(LS_INFO) << "channel: " << videoChannel << " usage: " << static_cast(usage) << " ssrc: " << SSRC; // Get the channel ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* ptrViEChannel = cs.Channel(videoChannel); if (ptrViEChannel == NULL) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (ptrViEChannel->SetRemoteSSRCType(usage, SSRC) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::GetLocalSSRC(const int video_channel, unsigned int& SSRC) const { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } uint8_t idx = 0; if (vie_channel->GetLocalSSRC(idx, &SSRC) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::GetRemoteSSRC(const int video_channel, unsigned int& SSRC) const { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->GetRemoteSSRC(&SSRC) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::GetRemoteCSRCs(const int video_channel, unsigned int CSRCs[kRtpCsrcSize]) const { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->GetRemoteCSRC(CSRCs) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::SetRtxSendPayloadType(const int video_channel, const uint8_t payload_type) { LOG_F(LS_INFO) << "channel: " << video_channel << " payload_type: " << static_cast(payload_type); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->SetRtxSendPayloadType(payload_type) != 0) { return -1; } return 0; } int ViERTP_RTCPImpl::SetPadWithRedundantPayloads(int video_channel, bool enable) { LOG_F(LS_INFO) << "channel: " << video_channel << " pad with redundant payloads: " << (enable ? "enable" : "disable"); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } vie_channel->SetPadWithRedundantPayloads(enable); return 0; } int ViERTP_RTCPImpl::SetRtxReceivePayloadType(const int video_channel, const uint8_t payload_type) { LOG_F(LS_INFO) << "channel: " << video_channel << " payload_type: " << static_cast(payload_type); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } vie_channel->SetRtxReceivePayloadType(payload_type); return 0; } int ViERTP_RTCPImpl::SetStartSequenceNumber(const int video_channel, uint16_t sequence_number) { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->Sending()) { LOG_F(LS_ERROR) << "channel " << video_channel << " is already sending."; shared_data_->SetLastError(kViERtpRtcpAlreadySending); return -1; } if (vie_channel->SetStartSequenceNumber(sequence_number) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } void ViERTP_RTCPImpl::SetRtpStateForSsrc(int video_channel, uint32_t ssrc, const RtpState& rtp_state) { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) return; if (vie_channel->Sending()) { LOG_F(LS_ERROR) << "channel " << video_channel << " is already sending."; return; } vie_channel->SetRtpStateForSsrc(ssrc, rtp_state); } RtpState ViERTP_RTCPImpl::GetRtpStateForSsrc(int video_channel, uint32_t ssrc) { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) return RtpState(); return vie_channel->GetRtpStateForSsrc(ssrc); } int ViERTP_RTCPImpl::SetRTCPStatus(const int video_channel, const ViERTCPMode rtcp_mode) { LOG_F(LS_INFO) << "channel: " << video_channel << " mode: " << static_cast(rtcp_mode); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } RTCPMethod module_mode = ViERTCPModeToRTCPMethod(rtcp_mode); if (vie_channel->SetRTCPMode(module_mode) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::GetRTCPStatus(const int video_channel, ViERTCPMode& rtcp_mode) const { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } RTCPMethod module_mode = kRtcpOff; if (vie_channel->GetRTCPMode(&module_mode) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } rtcp_mode = RTCPMethodToViERTCPMode(module_mode); return 0; } int ViERTP_RTCPImpl::SetRTCPCName(const int video_channel, const char rtcp_cname[KMaxRTCPCNameLength]) { LOG_F(LS_INFO) << "channel: " << video_channel << " rtcp_cname: " << rtcp_cname; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->Sending()) { LOG_F(LS_ERROR) << "channel " << video_channel << " is already sending."; shared_data_->SetLastError(kViERtpRtcpAlreadySending); return -1; } if (vie_channel->SetRTCPCName(rtcp_cname) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::GetRemoteRTCPCName( const int video_channel, char rtcp_cname[KMaxRTCPCNameLength]) const { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->GetRemoteRTCPCName(rtcp_cname) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::SendApplicationDefinedRTCPPacket( const int video_channel, const unsigned char sub_type, unsigned int name, const char* data, uint16_t data_length_in_bytes) { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (!vie_channel->Sending()) { shared_data_->SetLastError(kViERtpRtcpNotSending); return -1; } RTCPMethod method; if (vie_channel->GetRTCPMode(&method) != 0 || method == kRtcpOff) { shared_data_->SetLastError(kViERtpRtcpRtcpDisabled); return -1; } if (vie_channel->SendApplicationDefinedRTCPPacket( sub_type, name, reinterpret_cast(data), data_length_in_bytes) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::SetNACKStatus(const int video_channel, const bool enable) { LOG_F(LS_INFO) << "channel: " << video_channel << " " << (enable ? "on" : "off"); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->SetNACKStatus(enable) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } // Update the encoder ViEEncoder* vie_encoder = cs.Encoder(video_channel); if (!vie_encoder) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } vie_encoder->UpdateProtectionMethod(enable); return 0; } int ViERTP_RTCPImpl::SetFECStatus(const int video_channel, const bool enable, const unsigned char payload_typeRED, const unsigned char payload_typeFEC) { LOG_F(LS_INFO) << "channel: " << video_channel << " enable: " << (enable ? "on" : "off") << " payload_typeRED: " << static_cast(payload_typeRED) << " payload_typeFEC: " << static_cast(payload_typeFEC); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->SetFECStatus(enable, payload_typeRED, payload_typeFEC) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } // Update the encoder. ViEEncoder* vie_encoder = cs.Encoder(video_channel); if (!vie_encoder) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } vie_encoder->UpdateProtectionMethod(false); return 0; } int ViERTP_RTCPImpl::SetHybridNACKFECStatus( const int video_channel, const bool enable, const unsigned char payload_typeRED, const unsigned char payload_typeFEC) { LOG_F(LS_INFO) << "channel: " << video_channel << " enable: " << (enable ? "on" : "off") << " payload_typeRED: " << static_cast(payload_typeRED) << " payload_typeFEC: " << static_cast(payload_typeFEC); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } // Update the channel status with hybrid NACK FEC mode. if (vie_channel->SetHybridNACKFECStatus(enable, payload_typeRED, payload_typeFEC) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } // Update the encoder. ViEEncoder* vie_encoder = cs.Encoder(video_channel); if (!vie_encoder) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } vie_encoder->UpdateProtectionMethod(enable); return 0; } int ViERTP_RTCPImpl::SetSenderBufferingMode(int video_channel, int target_delay_ms) { LOG_F(LS_INFO) << "channel: " << video_channel << " target_delay_ms: " << target_delay_ms; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } ViEEncoder* vie_encoder = cs.Encoder(video_channel); if (!vie_encoder) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } // Update the channel with buffering mode settings. if (vie_channel->SetSenderBufferingMode(target_delay_ms) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } // Update the encoder's buffering mode settings. vie_encoder->SetSenderBufferingMode(target_delay_ms); return 0; } int ViERTP_RTCPImpl::SetReceiverBufferingMode(int video_channel, int target_delay_ms) { LOG_F(LS_INFO) << "channel: " << video_channel << " target_delay_ms: " << target_delay_ms; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } // Update the channel with buffering mode settings. if (vie_channel->SetReceiverBufferingMode(target_delay_ms) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::SetKeyFrameRequestMethod( const int video_channel, const ViEKeyFrameRequestMethod method) { LOG_F(LS_INFO) << "channel: " << video_channel << " method: " << static_cast(method); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } KeyFrameRequestMethod module_method = APIRequestToModuleRequest(method); if (vie_channel->SetKeyFrameRequestMethod(module_method) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::SetTMMBRStatus(const int video_channel, const bool enable) { LOG_F(LS_INFO) << "channel: " << video_channel << "enable: " << (enable ? "on" : "off"); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->EnableTMMBR(enable) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::SetRembStatus(int video_channel, bool sender, bool receiver) { LOG_F(LS_INFO) << "channel: " << video_channel << " sender: " << (sender ? "on" : "off") << " receiver: " << (receiver ? "on" : "off"); if (!shared_data_->channel_manager()->SetRembStatus(video_channel, sender, receiver)) { return -1; } return 0; } int ViERTP_RTCPImpl::SetSendTimestampOffsetStatus(int video_channel, bool enable, int id) { LOG_F(LS_INFO) << "channel: " << video_channel << "enable: " << (enable ? "on" : "off") << " id: " << id; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->SetSendTimestampOffsetStatus(enable, id) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::SetReceiveTimestampOffsetStatus(int video_channel, bool enable, int id) { LOG_F(LS_INFO) << "channel: " << video_channel << "enable: " << (enable ? "on" : "off") << " id: " << id; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->SetReceiveTimestampOffsetStatus(enable, id) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::SetSendAbsoluteSendTimeStatus(int video_channel, bool enable, int id) { LOG_F(LS_INFO) << "channel: " << video_channel << "enable: " << (enable ? "on" : "off") << " id: " << id; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->SetSendAbsoluteSendTimeStatus(enable, id) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::SetReceiveAbsoluteSendTimeStatus(int video_channel, bool enable, int id) { LOG_F(LS_INFO) << "channel: " << video_channel << "enable: " << (enable ? "on" : "off") << " id: " << id; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->SetReceiveAbsoluteSendTimeStatus(enable, id) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::SetRtcpXrRrtrStatus(int video_channel, bool enable) { LOG_F(LS_INFO) << "channel: " << video_channel << " enable: " << (enable ? "on" : "off"); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } vie_channel->SetRtcpXrRrtrStatus(enable); return 0; } int ViERTP_RTCPImpl::SetTransmissionSmoothingStatus(int video_channel, bool enable) { LOG_F(LS_INFO) << "channel: " << video_channel << " enable: " << (enable ? "on" : "off"); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } vie_channel->SetTransmissionSmoothingStatus(enable); return 0; } int ViERTP_RTCPImpl::SetMinTransmitBitrate(int video_channel, int min_transmit_bitrate_kbps) { LOG_F(LS_INFO) << "channel: " << video_channel << " min_transmit_bitrate_kbps: " << min_transmit_bitrate_kbps; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEEncoder* vie_encoder = cs.Encoder(video_channel); if (vie_encoder == NULL) return -1; vie_encoder->SetMinTransmitBitrate(min_transmit_bitrate_kbps); return 0; } int ViERTP_RTCPImpl::SetReservedTransmitBitrate( int video_channel, unsigned int reserved_transmit_bitrate_bps) { LOG_F(LS_INFO) << "channel: " << video_channel << " reserved_transmit_bitrate_bps: " << reserved_transmit_bitrate_bps; if (!shared_data_->channel_manager()->SetReservedTransmitBitrate( video_channel, reserved_transmit_bitrate_bps)) { return -1; } return 0; } int ViERTP_RTCPImpl::GetReceiveChannelRtcpStatistics( const int video_channel, RtcpStatistics& basic_stats, int& rtt_ms) const { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } // TODO(sprang): Clean this up when stats struct is propagated all the way. uint16_t frac_lost; if (vie_channel->GetReceivedRtcpStatistics( &frac_lost, &basic_stats.cumulative_lost, &basic_stats.extended_max_sequence_number, &basic_stats.jitter, &rtt_ms) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } basic_stats.fraction_lost = frac_lost; return 0; } int ViERTP_RTCPImpl::GetSendChannelRtcpStatistics(const int video_channel, RtcpStatistics& basic_stats, int& rtt_ms) const { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } // TODO(sprang): Clean this up when stats struct is propagated all the way. uint16_t frac_lost; if (vie_channel->GetSendRtcpStatistics( &frac_lost, &basic_stats.cumulative_lost, &basic_stats.extended_max_sequence_number, &basic_stats.jitter, &rtt_ms) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } basic_stats.fraction_lost = frac_lost; return 0; } int ViERTP_RTCPImpl::GetRtpStatistics(const int video_channel, StreamDataCounters& sent, StreamDataCounters& received) const { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->GetRtpStatistics(&sent.bytes, &sent.packets, &received.bytes, &received.packets) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::GetRtcpPacketTypeCounters( int video_channel, RtcpPacketTypeCounter* packets_sent, RtcpPacketTypeCounter* packets_received) const { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } vie_channel->GetRtcpPacketTypeCounters(packets_sent, packets_received); return 0; } int ViERTP_RTCPImpl::GetBandwidthUsage(const int video_channel, unsigned int& total_bitrate_sent, unsigned int& video_bitrate_sent, unsigned int& fec_bitrate_sent, unsigned int& nackBitrateSent) const { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } vie_channel->GetBandwidthUsage(&total_bitrate_sent, &video_bitrate_sent, &fec_bitrate_sent, &nackBitrateSent); return 0; } int ViERTP_RTCPImpl::GetEstimatedSendBandwidth( const int video_channel, unsigned int* estimated_bandwidth) const { if (!shared_data_->channel_manager()->GetEstimatedSendBandwidth( video_channel, estimated_bandwidth)) { return -1; } return 0; } int ViERTP_RTCPImpl::GetEstimatedReceiveBandwidth( const int video_channel, unsigned int* estimated_bandwidth) const { if (!shared_data_->channel_manager()->GetEstimatedReceiveBandwidth( video_channel, estimated_bandwidth)) { return -1; } return 0; } int ViERTP_RTCPImpl::GetReceiveBandwidthEstimatorStats( const int video_channel, ReceiveBandwidthEstimatorStats* output) const { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } vie_channel->GetReceiveBandwidthEstimatorStats(output); return 0; } int ViERTP_RTCPImpl::GetPacerQueuingDelayMs( const int video_channel, int* delay_ms) const { ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEEncoder* vie_encoder = cs.Encoder(video_channel); if (!vie_encoder) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } *delay_ms = vie_encoder->PacerQueuingDelayMs(); return 0; } int ViERTP_RTCPImpl::StartRTPDump(const int video_channel, const char file_nameUTF8[1024], RTPDirections direction) { LOG_F(LS_INFO) << "channel: " << video_channel << " filename: " << file_nameUTF8 << " direction: " << static_cast(direction); assert(FileWrapper::kMaxFileNameSize == 1024); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->StartRTPDump(file_nameUTF8, direction) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::StopRTPDump(const int video_channel, RTPDirections direction) { LOG_F(LS_INFO) << "channel: " << video_channel << " direction: " << static_cast(direction); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->StopRTPDump(direction) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::RegisterRTPObserver(const int video_channel, ViERTPObserver& observer) { LOG_F(LS_INFO) << "channel " << video_channel; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->RegisterRtpObserver(&observer) != 0) { shared_data_->SetLastError(kViERtpRtcpObserverAlreadyRegistered); return -1; } return 0; } int ViERTP_RTCPImpl::DeregisterRTPObserver(const int video_channel) { LOG_F(LS_INFO) << "channel " << video_channel; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->RegisterRtpObserver(NULL) != 0) { shared_data_->SetLastError(kViERtpRtcpObserverNotRegistered); return -1; } return 0; } int ViERTP_RTCPImpl::RegisterRTCPObserver(const int video_channel, ViERTCPObserver& observer) { LOG_F(LS_INFO) << "channel " << video_channel; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->RegisterRtcpObserver(&observer) != 0) { shared_data_->SetLastError(kViERtpRtcpObserverAlreadyRegistered); return -1; } return 0; } int ViERTP_RTCPImpl::DeregisterRTCPObserver(const int video_channel) { LOG_F(LS_INFO) << "channel " << video_channel; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->RegisterRtcpObserver(NULL) != 0) { shared_data_->SetLastError(kViERtpRtcpObserverNotRegistered); return -1; } return 0; } int ViERTP_RTCPImpl::RegisterSendChannelRtcpStatisticsCallback( int video_channel, RtcpStatisticsCallback* callback) { LOG_F(LS_INFO) << "channel " << video_channel; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } vie_channel->RegisterSendChannelRtcpStatisticsCallback(callback); return 0; } int ViERTP_RTCPImpl::DeregisterSendChannelRtcpStatisticsCallback( int video_channel, RtcpStatisticsCallback* callback) { LOG_F(LS_INFO) << "channel " << video_channel; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } vie_channel->RegisterSendChannelRtcpStatisticsCallback(NULL); return 0; } int ViERTP_RTCPImpl::RegisterReceiveChannelRtcpStatisticsCallback( const int video_channel, RtcpStatisticsCallback* callback) { LOG_F(LS_INFO) << "channel " << video_channel; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); assert(vie_channel != NULL); vie_channel->RegisterReceiveChannelRtcpStatisticsCallback(callback); return 0; } int ViERTP_RTCPImpl::DeregisterReceiveChannelRtcpStatisticsCallback( const int video_channel, RtcpStatisticsCallback* callback) { LOG_F(LS_INFO) << "channel " << video_channel; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); assert(vie_channel != NULL); vie_channel->RegisterReceiveChannelRtcpStatisticsCallback(NULL); return 0; } int ViERTP_RTCPImpl::RegisterSendChannelRtpStatisticsCallback( int video_channel, StreamDataCountersCallback* callback) { LOG_F(LS_INFO) << "channel " << video_channel; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); assert(vie_channel != NULL); vie_channel->RegisterSendChannelRtpStatisticsCallback(callback); return 0; } int ViERTP_RTCPImpl::DeregisterSendChannelRtpStatisticsCallback( int video_channel, StreamDataCountersCallback* callback) { LOG_F(LS_INFO) << "channel " << video_channel; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); assert(vie_channel != NULL); vie_channel->RegisterSendChannelRtpStatisticsCallback(NULL); return 0; } int ViERTP_RTCPImpl::RegisterReceiveChannelRtpStatisticsCallback( const int video_channel, StreamDataCountersCallback* callback) { LOG_F(LS_INFO) << "channel " << video_channel; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); assert(vie_channel != NULL); vie_channel->RegisterReceiveChannelRtpStatisticsCallback(callback); return 0; } int ViERTP_RTCPImpl::DeregisterReceiveChannelRtpStatisticsCallback( const int video_channel, StreamDataCountersCallback* callback) { LOG_F(LS_INFO) << "channel " << video_channel; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); assert(vie_channel != NULL); vie_channel->RegisterReceiveChannelRtpStatisticsCallback(NULL); return 0; } // Called whenever the send bitrate is updated. int ViERTP_RTCPImpl::RegisterSendBitrateObserver( const int video_channel, BitrateStatisticsObserver* observer) { LOG_F(LS_INFO) << "channel " << video_channel; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); assert(vie_channel != NULL); vie_channel->RegisterSendBitrateObserver(observer); return 0; } int ViERTP_RTCPImpl::DeregisterSendBitrateObserver( const int video_channel, BitrateStatisticsObserver* observer) { LOG_F(LS_INFO) << "channel " << video_channel; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); assert(vie_channel != NULL); vie_channel->RegisterSendBitrateObserver(NULL); return 0; } int ViERTP_RTCPImpl::RegisterSendFrameCountObserver( int video_channel, FrameCountObserver* callback) { LOG_F(LS_INFO) << "channel " << video_channel; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } vie_channel->RegisterSendFrameCountObserver(callback); return 0; } int ViERTP_RTCPImpl::DeregisterSendFrameCountObserver( int video_channel, FrameCountObserver* callback) { LOG_F(LS_INFO) << "channel " << video_channel; ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } vie_channel->RegisterSendFrameCountObserver(NULL); return 0; } } // namespace webrtc