/* * 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/trace.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() { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, shared_data_->instance_id(), "ViERTP_RTCP::Release()"); // Decrease ref count. (*this)--; int32_t ref_count = GetCount(); if (ref_count < 0) { WEBRTC_TRACE(kTraceWarning, kTraceVideo, shared_data_->instance_id(), "ViERTP_RTCP release too many times"); shared_data_->SetLastError(kViEAPIDoesNotExist); return -1; } WEBRTC_TRACE(kTraceInfo, kTraceVideo, shared_data_->instance_id(), "ViERTP_RTCP reference count: %d", ref_count); return ref_count; } ViERTP_RTCPImpl::ViERTP_RTCPImpl(ViESharedData* shared_data) : shared_data_(shared_data) { WEBRTC_TRACE(kTraceMemory, kTraceVideo, shared_data_->instance_id(), "ViERTP_RTCPImpl::ViERTP_RTCPImpl() Ctor"); } ViERTP_RTCPImpl::~ViERTP_RTCPImpl() { WEBRTC_TRACE(kTraceMemory, kTraceVideo, shared_data_->instance_id(), "ViERTP_RTCPImpl::~ViERTP_RTCPImpl() Dtor"); } int ViERTP_RTCPImpl::SetLocalSSRC(const int video_channel, const unsigned int SSRC, const StreamType usage, const unsigned char simulcast_idx) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d, SSRC: %d)", __FUNCTION__, video_channel, SSRC); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { // The channel doesn't exists WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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 { WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, ViEId(shared_data_->instance_id(), videoChannel), "%s(channel: %d, usage:%d SSRC: 0x%x)", __FUNCTION__, usage, videoChannel, SSRC); // Get the channel ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* ptrViEChannel = cs.Channel(videoChannel); if (ptrViEChannel == NULL) { // The channel doesn't exists WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(shared_data_->instance_id(), videoChannel), "%s: Channel %d doesn't exist", __FUNCTION__, videoChannel); 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 { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d, SSRC: %d)", __FUNCTION__, video_channel, SSRC); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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 { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel, SSRC); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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 { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->SetRtxSendPayloadType(payload_type) != 0) { return -1; } return 0; } int ViERTP_RTCPImpl::SetRtxReceivePayloadType(const int video_channel, const uint8_t payload_type) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d, sequence_number: %u)", __FUNCTION__, video_channel, sequence_number); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->Sending()) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d already sending.", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpAlreadySending); return -1; } if (vie_channel->SetStartSequenceNumber(sequence_number) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::SetRTCPStatus(const int video_channel, const ViERTCPMode rtcp_mode) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d, mode: %d)", __FUNCTION__, video_channel, rtcp_mode); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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 { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel, rtcp_mode); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } RTCPMethod module_mode = kRtcpOff; if (vie_channel->GetRTCPMode(&module_mode) != 0) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: could not get current RTCP mode", __FUNCTION__); 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]) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d, name: %s)", __FUNCTION__, video_channel, rtcp_cname); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->Sending()) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d already sending.", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpAlreadySending); return -1; } if (vie_channel->SetRTCPCName(rtcp_cname) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::GetRTCPCName(const int video_channel, char rtcp_cname[KMaxRTCPCNameLength]) const { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->GetRTCPCName(rtcp_cname) != 0) { shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::GetRemoteRTCPCName( const int video_channel, char rtcp_cname[KMaxRTCPCNameLength]) const { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d, sub_type: %c, name: %d, data: x, length: %u)", __FUNCTION__, video_channel, sub_type, name, data_length_in_bytes); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (!vie_channel->Sending()) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d not sending", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpNotSending); return -1; } RTCPMethod method; if (vie_channel->GetRTCPMode(&method) != 0 || method == kRtcpOff) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: RTCP disabled on channel %d.", __FUNCTION__, video_channel); 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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d, enable: %d)", __FUNCTION__, video_channel, enable); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->SetNACKStatus(enable) != 0) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: failed for channel %d", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } // Update the encoder ViEEncoder* vie_encoder = cs.Encoder(video_channel); if (!vie_encoder) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Could not get encoder for channel %d", __FUNCTION__, video_channel); 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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d, enable: %d, payload_typeRED: %u, " "payloadTypeFEC: %u)", __FUNCTION__, video_channel, enable, payload_typeRED, payload_typeFEC); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } if (vie_channel->SetFECStatus(enable, payload_typeRED, payload_typeFEC) != 0) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: failed for channel %d", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } // Update the encoder. ViEEncoder* vie_encoder = cs.Encoder(video_channel); if (!vie_encoder) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Could not get encoder for channel %d", __FUNCTION__, video_channel); 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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d, enable: %d, payload_typeRED: %u, " "payloadTypeFEC: %u)", __FUNCTION__, video_channel, enable, payload_typeRED, payload_typeFEC); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: failed for channel %d", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } // Update the encoder. ViEEncoder* vie_encoder = cs.Encoder(video_channel); if (!vie_encoder) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Could not get encoder for channel %d", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } vie_encoder->UpdateProtectionMethod(enable); return 0; } int ViERTP_RTCPImpl::SetSenderBufferingMode(int video_channel, int target_delay_ms) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d, sender target_delay: %d)", __FUNCTION__, video_channel, target_delay_ms); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } ViEEncoder* vie_encoder = cs.Encoder(video_channel); if (!vie_encoder) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Could not get encoder for channel %d", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } // Update the channel with buffering mode settings. if (vie_channel->SetSenderBufferingMode(target_delay_ms) != 0) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: failed for channel %d", __FUNCTION__, video_channel); 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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d, receiver target_delay: %d)", __FUNCTION__, video_channel, target_delay_ms); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } // Update the channel with buffering mode settings. if (vie_channel->SetReceiverBufferingMode(target_delay_ms) != 0) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: failed for channel %d", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpUnknownError); return -1; } return 0; } int ViERTP_RTCPImpl::SetKeyFrameRequestMethod( const int video_channel, const ViEKeyFrameRequestMethod method) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d, method: %d)", __FUNCTION__, video_channel, method); // Get the channel. ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d, enable: %d)", __FUNCTION__, video_channel, enable); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "ViERTP_RTCPImpl::SetRembStatus(%d, %d, %d)", video_channel, sender, receiver); 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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "ViERTP_RTCPImpl::SetSendTimestampOffsetStatus(%d, %d, %d)", video_channel, enable, id); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "ViERTP_RTCPImpl::SetReceiveTimestampOffsetStatus(%d, %d, %d)", video_channel, enable, id); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "ViERTP_RTCPImpl::SetSendAbsoluteSendTimeStatus(%d, %d, %d)", video_channel, enable, id); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "ViERTP_RTCPImpl::SetReceiveAbsoluteSendTimeStatus(%d, %d, %d)", video_channel, enable, id); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "ViERTP_RTCPImpl::SetRtcpXrRrtrStatus(%d, %d)", video_channel, enable); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } vie_channel->SetRtcpXrRrtrStatus(enable); return 0; } int ViERTP_RTCPImpl::SetTransmissionSmoothingStatus(int video_channel, bool enable) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d, enble: %d)", __FUNCTION__, video_channel, enable); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } vie_channel->SetTransmissionSmoothingStatus(enable); return 0; } int ViERTP_RTCPImpl::GetReceiveChannelRtcpStatistics( const int video_channel, RtcpStatistics& basic_stats, int& rtt_ms) const { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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 { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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 { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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 { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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 { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEEncoder* vie_encoder = cs.Encoder(video_channel); if (!vie_encoder) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Could not get encoder for channel %d", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } return vie_encoder->EstimatedSendBandwidth( static_cast(estimated_bandwidth)); } int ViERTP_RTCPImpl::GetEstimatedReceiveBandwidth( const int video_channel, unsigned int* estimated_bandwidth) const { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Could not get channel %d", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } vie_channel->GetEstimatedReceiveBandwidth( static_cast(estimated_bandwidth)); return 0; } int ViERTP_RTCPImpl::GetReceiveBandwidthEstimatorStats( const int video_channel, ReceiveBandwidthEstimatorStats* output) const { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Could not get channel %d", __FUNCTION__, video_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 { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEEncoder* vie_encoder = cs.Encoder(video_channel); if (!vie_encoder) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Could not get encoder for channel %d", __FUNCTION__, video_channel); 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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d, file_name: %s, direction: %d)", __FUNCTION__, video_channel, file_nameUTF8, direction); assert(FileWrapper::kMaxFileNameSize == 1024); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d, direction: %d)", __FUNCTION__, video_channel, direction); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } vie_channel->RegisterSendChannelRtcpStatisticsCallback(callback); return 0; } int ViERTP_RTCPImpl::DeregisterSendChannelRtcpStatisticsCallback( int video_channel, RtcpStatisticsCallback* callback) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } vie_channel->RegisterSendChannelRtcpStatisticsCallback(NULL); return 0; } int ViERTP_RTCPImpl::RegisterReceiveChannelRtcpStatisticsCallback( const int video_channel, RtcpStatisticsCallback* callback) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, 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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, 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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, 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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, 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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, 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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, 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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, 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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, 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) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } vie_channel->RegisterSendFrameCountObserver(callback); return 0; } int ViERTP_RTCPImpl::DeregisterSendFrameCountObserver( int video_channel, FrameCountObserver* callback) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s(channel: %d)", __FUNCTION__, video_channel); ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); ViEChannel* vie_channel = cs.Channel(video_channel); if (!vie_channel) { WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id(), video_channel), "%s: Channel %d doesn't exist", __FUNCTION__, video_channel); shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); return -1; } vie_channel->RegisterSendFrameCountObserver(NULL); return 0; } } // namespace webrtc