diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc index bfc8266725..8bde0a80f8 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc @@ -13,6 +13,8 @@ #include #include +#include + #include "webrtc/common_types.h" #include "webrtc/system_wrappers/interface/logging.h" #include "webrtc/system_wrappers/interface/trace.h" @@ -491,74 +493,21 @@ int32_t ModuleRtpRtcpImpl::SendOutgoingData( size_t payload_size, const RTPFragmentationHeader* fragmentation, const RTPVideoHeader* rtp_video_hdr) { - rtcp_sender_.SetLastRtpTime(time_stamp, capture_time_ms); + assert(!IsDefaultModule()); - if (!IsDefaultModule()) { - // Don't send RTCP from default module. - if (rtcp_sender_.TimeToSendRTCPReport(kVideoFrameKey == frame_type)) { + rtcp_sender_.SetLastRtpTime(time_stamp, capture_time_ms); + if (rtcp_sender_.TimeToSendRTCPReport(kVideoFrameKey == frame_type)) { rtcp_sender_.SendRTCP(GetFeedbackState(), kRtcpReport); - } - return rtp_sender_.SendOutgoingData(frame_type, - payload_type, - time_stamp, - capture_time_ms, - payload_data, - payload_size, - fragmentation, - NULL, - &(rtp_video_hdr->codecHeader)); } - int32_t ret_val = -1; - CriticalSectionScoped lock(critical_section_module_ptrs_.get()); - if (simulcast_) { - if (rtp_video_hdr == NULL) { - return -1; - } - int idx = 0; - std::vector::iterator it = child_modules_.begin(); - for (; idx < rtp_video_hdr->simulcastIdx; ++it) { - if (it == child_modules_.end()) { - return -1; - } - if ((*it)->SendingMedia()) { - ++idx; - } - } - for (; it != child_modules_.end(); ++it) { - if ((*it)->SendingMedia()) { - break; - } - ++idx; - } - if (it == child_modules_.end()) { - return -1; - } - return (*it)->SendOutgoingData(frame_type, - payload_type, - time_stamp, - capture_time_ms, - payload_data, - payload_size, - fragmentation, - rtp_video_hdr); - } else { - std::vector::iterator it = child_modules_.begin(); - // Send to all "child" modules - while (it != child_modules_.end()) { - if ((*it)->SendingMedia()) { - ret_val = (*it)->SendOutgoingData(frame_type, - payload_type, - time_stamp, - capture_time_ms, - payload_data, - payload_size, - fragmentation, - rtp_video_hdr); - } - it++; - } - } - return ret_val; + return rtp_sender_.SendOutgoingData(frame_type, + payload_type, + time_stamp, + capture_time_ms, + payload_data, + payload_size, + fragmentation, + NULL, + &(rtp_video_hdr->codecHeader)); } bool ModuleRtpRtcpImpl::TimeToSendPacket(uint32_t ssrc, @@ -1346,4 +1295,4 @@ bool ModuleRtpRtcpImpl::IsDefaultModule() const { return !child_modules_.empty(); } -} // Namespace webrtc +} // namespace webrtc diff --git a/webrtc/video_engine/BUILD.gn b/webrtc/video_engine/BUILD.gn index 889e054e94..99c16ac9e2 100644 --- a/webrtc/video_engine/BUILD.gn +++ b/webrtc/video_engine/BUILD.gn @@ -29,6 +29,8 @@ source_set("video_engine_core") { "encoder_state_feedback.h", "overuse_frame_detector.cc", "overuse_frame_detector.h", + "payload_router.cc", + "payload_router.h", "report_block_stats.cc", "report_block_stats.h", "stream_synchronization.cc", diff --git a/webrtc/video_engine/payload_router.cc b/webrtc/video_engine/payload_router.cc new file mode 100644 index 0000000000..f815d13a66 --- /dev/null +++ b/webrtc/video_engine/payload_router.cc @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015 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/payload_router.h" + +#include "webrtc/base/checks.h" +#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" +#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" + +namespace webrtc { + +PayloadRouter::PayloadRouter() + : crit_(CriticalSectionWrapper::CreateCriticalSection()), + active_(false) {} + +PayloadRouter::~PayloadRouter() {} + +void PayloadRouter::SetSendingRtpModules( + const std::list& rtp_modules) { + CriticalSectionScoped cs(crit_.get()); + rtp_modules_.clear(); + rtp_modules_.reserve(rtp_modules.size()); + for (auto* rtp_module : rtp_modules) { + rtp_modules_.push_back(rtp_module); + } +} + +void PayloadRouter::set_active(bool active) { + CriticalSectionScoped cs(crit_.get()); + active_ = active; +} + +bool PayloadRouter::active() { + CriticalSectionScoped cs(crit_.get()); + return active_; +} + +bool PayloadRouter::RoutePayload(FrameType frame_type, + int8_t payload_type, + uint32_t time_stamp, + int64_t capture_time_ms, + const uint8_t* payload_data, + size_t payload_size, + const RTPFragmentationHeader* fragmentation, + const RTPVideoHeader* rtp_video_hdr) { + CriticalSectionScoped cs(crit_.get()); + DCHECK(rtp_video_hdr == NULL || + rtp_video_hdr->simulcastIdx <= rtp_modules_.size()); + + if (!active_ || rtp_modules_.empty()) + return false; + + int stream_idx = 0; + if (rtp_video_hdr != NULL) + stream_idx = rtp_video_hdr->simulcastIdx; + return rtp_modules_[stream_idx]->SendOutgoingData( + frame_type, payload_type, time_stamp, capture_time_ms, payload_data, + payload_size, fragmentation, rtp_video_hdr) == 0 ? true : false; +} + +} // namespace webrtc diff --git a/webrtc/video_engine/payload_router.h b/webrtc/video_engine/payload_router.h new file mode 100644 index 0000000000..3cc0bb0a61 --- /dev/null +++ b/webrtc/video_engine/payload_router.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015 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_VIDEO_ENGINE_PAYLOAD_ROUTER_H_ +#define WEBRTC_VIDEO_ENGINE_PAYLOAD_ROUTER_H_ + +#include +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/thread_annotations.h" +#include "webrtc/common_types.h" +#include "webrtc/system_wrappers/interface/scoped_ptr.h" + +namespace webrtc { + +class CriticalSectionWrapper; +class RTPFragmentationHeader; +class RtpRtcp; +struct RTPVideoHeader; + +// PayloadRouter routes outgoing data to the correct sending RTP module, based +// on the simulcast layer in RTPVideoHeader. +class PayloadRouter { + public: + PayloadRouter(); + ~PayloadRouter(); + + // Rtp modules are assumed to be sorted in simulcast index order. + void SetSendingRtpModules(const std::list& rtp_modules); + + // PayloadRouter will only route packets if being active, all packets will be + // dropped otherwise. + void set_active(bool active); + bool active(); + + // Input parameters according to the signature of RtpRtcp::SendOutgoingData. + // Returns true if the packet was routed / sent, false otherwise. + bool RoutePayload(FrameType frame_type, + int8_t payload_type, + uint32_t time_stamp, + int64_t capture_time_ms, + const uint8_t* payload_data, + size_t payload_size, + const RTPFragmentationHeader* fragmentation, + const RTPVideoHeader* rtp_video_hdr); + + private: + scoped_ptr crit_; + + // Active sending RTP modules, in layer order. + std::vector rtp_modules_ GUARDED_BY(crit_.get()); + bool active_ GUARDED_BY(crit_.get()); + + DISALLOW_COPY_AND_ASSIGN(PayloadRouter); +}; + +} // namespace webrtc + +#endif // WEBRTC_VIDEO_ENGINE_PAYLOAD_ROUTER_H_ diff --git a/webrtc/video_engine/payload_router_unittest.cc b/webrtc/video_engine/payload_router_unittest.cc new file mode 100644 index 0000000000..b4d20bf4eb --- /dev/null +++ b/webrtc/video_engine/payload_router_unittest.cc @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2015 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 + +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" +#include "webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h" +#include "webrtc/system_wrappers/interface/scoped_ptr.h" +#include "webrtc/video_engine/payload_router.h" + +using ::testing::_; +using ::testing::AnyNumber; +using ::testing::NiceMock; +using ::testing::Return; + +namespace webrtc { + +class PayloadRouterTest : public ::testing::Test { + protected: + virtual void SetUp() { + payload_router_.reset(new PayloadRouter()); + } + scoped_ptr payload_router_; +}; + +TEST_F(PayloadRouterTest, SendOnOneModule) { + MockRtpRtcp rtp; + std::list modules(1, &rtp); + + payload_router_->SetSendingRtpModules(modules); + + uint8_t payload = 'a'; + FrameType frame_type = kVideoFrameKey; + int8_t payload_type = 96; + + EXPECT_CALL(rtp, SendOutgoingData(frame_type, payload_type, 0, 0, _, 1, NULL, + NULL)) + .Times(0); + EXPECT_FALSE(payload_router_->RoutePayload(frame_type, payload_type, 0, 0, + &payload, 1, NULL, NULL)); + + payload_router_->set_active(true); + EXPECT_CALL(rtp, SendOutgoingData(frame_type, payload_type, 0, 0, _, 1, NULL, + NULL)) + .Times(1); + EXPECT_TRUE(payload_router_->RoutePayload(frame_type, payload_type, 0, 0, + &payload, 1, NULL, NULL)); + + payload_router_->set_active(false); + EXPECT_CALL(rtp, SendOutgoingData(frame_type, payload_type, 0, 0, _, 1, NULL, + NULL)) + .Times(0); + EXPECT_FALSE(payload_router_->RoutePayload(frame_type, payload_type, 0, 0, + &payload, 1, NULL, NULL)); + + payload_router_->set_active(true); + EXPECT_CALL(rtp, SendOutgoingData(frame_type, payload_type, 0, 0, _, 1, NULL, + NULL)) + .Times(1); + EXPECT_TRUE(payload_router_->RoutePayload(frame_type, payload_type, 0, 0, + &payload, 1, NULL, NULL)); + + modules.clear(); + payload_router_->SetSendingRtpModules(modules); + EXPECT_CALL(rtp, SendOutgoingData(frame_type, payload_type, 0, 0, _, 1, NULL, + NULL)) + .Times(0); + EXPECT_FALSE(payload_router_->RoutePayload(frame_type, payload_type, 0, 0, + &payload, 1, NULL, NULL)); +} + +TEST_F(PayloadRouterTest, SendSimulcast) { + MockRtpRtcp rtp_1; + MockRtpRtcp rtp_2; + std::list modules; + modules.push_back(&rtp_1); + modules.push_back(&rtp_2); + + payload_router_->SetSendingRtpModules(modules); + + uint8_t payload_1 = 'a'; + FrameType frame_type_1 = kVideoFrameKey; + int8_t payload_type_1 = 96; + RTPVideoHeader rtp_hdr_1; + rtp_hdr_1.simulcastIdx = 0; + + payload_router_->set_active(true); + EXPECT_CALL(rtp_1, SendOutgoingData(frame_type_1, payload_type_1, 0, 0, _, 1, + NULL, &rtp_hdr_1)) + .Times(1); + EXPECT_CALL(rtp_2, SendOutgoingData(_, _, _, _, _, _, _, _)) + .Times(0); + EXPECT_TRUE(payload_router_->RoutePayload(frame_type_1, payload_type_1, 0, 0, + &payload_1, 1, NULL, &rtp_hdr_1)); + + uint8_t payload_2 = 'b'; + FrameType frame_type_2 = kVideoFrameDelta; + int8_t payload_type_2 = 97; + RTPVideoHeader rtp_hdr_2; + rtp_hdr_2.simulcastIdx = 1; + EXPECT_CALL(rtp_2, SendOutgoingData(frame_type_2, payload_type_2, 0, 0, _, 1, + NULL, &rtp_hdr_2)) + .Times(1); + EXPECT_CALL(rtp_1, SendOutgoingData(_, _, _, _, _, _, _, _)) + .Times(0); + EXPECT_TRUE(payload_router_->RoutePayload(frame_type_2, payload_type_2, 0, 0, + &payload_2, 1, NULL, &rtp_hdr_2)); + + payload_router_->set_active(false); + EXPECT_CALL(rtp_1, SendOutgoingData(_, _, _, _, _, _, _, _)) + .Times(0); + EXPECT_CALL(rtp_2, SendOutgoingData(_, _, _, _, _, _, _, _)) + .Times(0); + EXPECT_FALSE(payload_router_->RoutePayload(frame_type_1, payload_type_1, 0, 0, + &payload_1, 1, NULL, &rtp_hdr_1)); + EXPECT_FALSE(payload_router_->RoutePayload(frame_type_2, payload_type_2, 0, 0, + &payload_2, 1, NULL, &rtp_hdr_2)); +} + + +} // namespace webrtc diff --git a/webrtc/video_engine/video_engine_core.gypi b/webrtc/video_engine/video_engine_core.gypi index 72e1c64c34..02726fb7bd 100644 --- a/webrtc/video_engine/video_engine_core.gypi +++ b/webrtc/video_engine/video_engine_core.gypi @@ -49,6 +49,7 @@ 'call_stats.h', 'encoder_state_feedback.h', 'overuse_frame_detector.h', + 'payload_router.h', 'report_block_stats.h', 'stream_synchronization.h', 'vie_base_impl.h', @@ -83,6 +84,7 @@ 'call_stats.cc', 'encoder_state_feedback.cc', 'overuse_frame_detector.cc', + 'payload_router.cc', 'report_block_stats.cc', 'stream_synchronization.cc', 'vie_base_impl.cc', @@ -134,6 +136,7 @@ 'call_stats_unittest.cc', 'encoder_state_feedback_unittest.cc', 'overuse_frame_detector_unittest.cc', + 'payload_router_unittest.cc', 'report_block_stats_unittest.cc', 'stream_synchronization_unittest.cc', 'vie_capturer_unittest.cc', diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc index 62cfd50c48..8057ca0b8e 100644 --- a/webrtc/video_engine/vie_channel.cc +++ b/webrtc/video_engine/vie_channel.cc @@ -34,6 +34,7 @@ #include "webrtc/video_engine/include/vie_errors.h" #include "webrtc/video_engine/include/vie_image_process.h" #include "webrtc/video_engine/include/vie_rtp_rtcp.h" +#include "webrtc/video_engine/payload_router.h" #include "webrtc/video_engine/report_block_stats.h" #include "webrtc/video_engine/vie_defines.h" @@ -79,6 +80,7 @@ ViEChannel::ViEChannel(int32_t channel_id, callback_cs_(CriticalSectionWrapper::CreateCriticalSection()), rtp_rtcp_cs_(CriticalSectionWrapper::CreateCriticalSection()), default_rtp_rtcp_(default_rtp_rtcp), + send_payload_router_(new PayloadRouter()), vcm_(VideoCodingModule::Create()), vie_receiver_(channel_id, vcm_, remote_bitrate_estimator, this), vie_sender_(channel_id), @@ -131,6 +133,11 @@ int32_t ViEChannel::Init() { if (paced_sender_) { rtp_rtcp_->SetStorePacketsStatus(true, nack_history_size_sender_); } + if (sender_) { + std::list send_rtp_modules(1, rtp_rtcp_.get()); + send_payload_router_->SetSendingRtpModules(send_rtp_modules); + send_payload_router_->set_active(true); + } if (vcm_->InitializeReceiver() != 0) { return -1; } @@ -173,6 +180,7 @@ ViEChannel::~ViEChannel() { module_process_thread_.DeRegisterModule(rtp_rtcp_.get()); module_process_thread_.DeRegisterModule(vcm_); module_process_thread_.DeRegisterModule(&vie_sync_); + send_payload_router_->SetSendingRtpModules(std::list()); while (simulcast_rtp_rtcp_.size() > 0) { std::list::iterator it = simulcast_rtp_rtcp_.begin(); RtpRtcp* rtp_rtcp = *it; @@ -322,6 +330,9 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec, // Stop and Start the RTP module -> trigger new SSRC, if an SSRC hasn't been // set explicitly. bool restart_rtp = false; + bool router_was_active = send_payload_router_->active(); + send_payload_router_->set_active(false); + send_payload_router_->SetSendingRtpModules(std::list()); if (rtp_rtcp_->Sending() && new_stream) { restart_rtp = true; rtp_rtcp_->SetSendingStatus(false); @@ -480,6 +491,16 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec, (*it)->SetSendingMediaStatus(true); } } + // Update the packet router with the sending RTP RTCP modules. + std::list active_send_modules; + active_send_modules.push_back(rtp_rtcp_.get()); + for (std::list::const_iterator cit = simulcast_rtp_rtcp_.begin(); + cit != simulcast_rtp_rtcp_.end(); ++cit) { + active_send_modules.push_back(*cit); + } + send_payload_router_->SetSendingRtpModules(active_send_modules); + if (router_was_active) + send_payload_router_->set_active(true); return 0; } @@ -854,7 +875,6 @@ void ViEChannel::EnableTMMBR(bool enable) { } int32_t ViEChannel::EnableKeyFrameRequestCallback(const bool enable) { - CriticalSectionScoped cs(callback_cs_.get()); if (enable && !codec_observer_) { LOG(LS_ERROR) << "No ViECodecObserver set."; @@ -1344,11 +1364,13 @@ int32_t ViEChannel::StartSend() { rtp_rtcp->SetSendingMediaStatus(true); rtp_rtcp->SetSendingStatus(true); } + send_payload_router_->set_active(true); return 0; } int32_t ViEChannel::StopSend() { UpdateHistogramsAtStopSend(); + send_payload_router_->set_active(false); CriticalSectionScoped cs(rtp_rtcp_cs_.get()); rtp_rtcp_->SetSendingMediaStatus(false); for (std::list::iterator it = simulcast_rtp_rtcp_.begin(); @@ -1478,6 +1500,10 @@ RtpRtcp* ViEChannel::rtp_rtcp() { return rtp_rtcp_.get(); } +PayloadRouter* ViEChannel::send_payload_router() { + return send_payload_router_.get(); +} + CallStatsObserver* ViEChannel::GetStatsObserver() { return stats_observer_.get(); } diff --git a/webrtc/video_engine/vie_channel.h b/webrtc/video_engine/vie_channel.h index bc91b3af71..5640f23813 100644 --- a/webrtc/video_engine/vie_channel.h +++ b/webrtc/video_engine/vie_channel.h @@ -38,6 +38,7 @@ class CriticalSectionWrapper; class EncodedImageCallback; class I420FrameCallback; class PacedSender; +class PayloadRouter; class ProcessThread; class ReceiveStatisticsProxy; class ReportBlockStats; @@ -301,6 +302,7 @@ class ViEChannel // Gets the modules used by the channel. RtpRtcp* rtp_rtcp(); + PayloadRouter* send_payload_router(); CallStatsObserver* GetStatsObserver(); @@ -467,6 +469,8 @@ class ViEChannel scoped_ptr rtp_rtcp_; std::list simulcast_rtp_rtcp_; std::list removed_rtp_rtcp_; + scoped_ptr send_payload_router_; + VideoCodingModule* const vcm_; ViEReceiver vie_receiver_; ViESender vie_sender_; diff --git a/webrtc/video_engine/vie_channel_manager.cc b/webrtc/video_engine/vie_channel_manager.cc index aef167fafe..a2dca8a43f 100644 --- a/webrtc/video_engine/vie_channel_manager.cc +++ b/webrtc/video_engine/vie_channel_manager.cc @@ -10,6 +10,8 @@ #include "webrtc/video_engine/vie_channel_manager.h" +#include + #include "webrtc/common.h" #include "webrtc/engine_configurations.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" @@ -114,6 +116,9 @@ int ViEChannelManager::CreateChannel(int* channel_id, delete group; return -1; } + // Connect the encoder with the send packet router, to enable sending. + vie_encoder->SetSendPayloadRouter( + channel_map_[new_channel_id]->send_payload_router()); // Add ViEEncoder to EncoderFeedBackObserver. unsigned int ssrc = 0; @@ -174,6 +179,10 @@ int ViEChannelManager::CreateChannel(int* channel_id, delete vie_encoder; vie_encoder = NULL; } + // Connect the encoder with the send packet router, to enable sending. + vie_encoder->SetSendPayloadRouter( + channel_map_[new_channel_id]->send_payload_router()); + // Register the ViEEncoder to get key frame requests for this channel. unsigned int ssrc = 0; int stream_idx = 0; diff --git a/webrtc/video_engine/vie_encoder.cc b/webrtc/video_engine/vie_encoder.cc index ca02002873..b86c259744 100644 --- a/webrtc/video_engine/vie_encoder.cc +++ b/webrtc/video_engine/vie_encoder.cc @@ -14,6 +14,7 @@ #include +#include "webrtc/base/checks.h" #include "webrtc/common_video/interface/video_image.h" #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" #include "webrtc/frame_callback.h" @@ -33,6 +34,7 @@ #include "webrtc/video/send_statistics_proxy.h" #include "webrtc/video_engine/include/vie_codec.h" #include "webrtc/video_engine/include/vie_image_process.h" +#include "webrtc/video_engine/payload_router.h" #include "webrtc/video_engine/vie_defines.h" namespace webrtc { @@ -137,6 +139,7 @@ ViEEncoder::ViEEncoder(int32_t engine_id, vcm_(*webrtc::VideoCodingModule::Create()), vpm_(*webrtc::VideoProcessingModule::Create(ViEModuleId(engine_id, channel_id))), + send_payload_router_(NULL), callback_cs_(CriticalSectionWrapper::CreateCriticalSection()), data_cs_(CriticalSectionWrapper::CreateCriticalSection()), bitrate_controller_(bitrate_controller), @@ -228,6 +231,11 @@ bool ViEEncoder::Init() { return true; } +void ViEEncoder::SetSendPayloadRouter(PayloadRouter* send_payload_router) { + DCHECK(send_payload_router_ == NULL); + send_payload_router_ = send_payload_router; +} + ViEEncoder::~ViEEncoder() { UpdateHistograms(); if (bitrate_controller_) { @@ -504,8 +512,10 @@ RtpRtcp* ViEEncoder::SendRtpRtcpModule() { void ViEEncoder::DeliverFrame(int id, I420VideoFrame* video_frame, const std::vector& csrcs) { - if (default_rtp_rtcp_->SendingMedia() == false) { - // We've paused or we have no channels attached, don't encode. + DCHECK(send_payload_router_ != NULL); + if (!default_rtp_rtcp_->SendingMedia() || !send_payload_router_->active()) { + // We've paused or we have no channels attached, don't waste resources on + // encoding. return; } { @@ -731,15 +741,17 @@ int32_t ViEEncoder::SendData( const EncodedImage& encoded_image, const webrtc::RTPFragmentationHeader& fragmentation_header, const RTPVideoHeader* rtp_video_hdr) { + DCHECK(send_payload_router_ != NULL); + if (send_statistics_proxy_ != NULL) { send_statistics_proxy_->OnSendEncodedImage(encoded_image, rtp_video_hdr); } - // New encoded data, hand over to the rtp module. - return default_rtp_rtcp_->SendOutgoingData( + + return send_payload_router_->RoutePayload( VCMEncodedFrame::ConvertFrameType(encoded_image._frameType), payload_type, encoded_image._timeStamp, encoded_image.capture_time_ms_, encoded_image._buffer, encoded_image._length, &fragmentation_header, - rtp_video_hdr); + rtp_video_hdr) ? 0 : -1; } int32_t ViEEncoder::ProtectionRequest( diff --git a/webrtc/video_engine/vie_encoder.h b/webrtc/video_engine/vie_encoder.h index ba7de53844..d1723bc8dc 100644 --- a/webrtc/video_engine/vie_encoder.h +++ b/webrtc/video_engine/vie_encoder.h @@ -13,6 +13,7 @@ #include #include +#include #include "webrtc/base/thread_annotations.h" #include "webrtc/common_types.h" @@ -32,6 +33,7 @@ class Config; class CriticalSectionWrapper; class EncodedImageCallback; class PacedSender; +class PayloadRouter; class ProcessThread; class QMVideoSettingsCallback; class RtpRtcp; @@ -62,6 +64,9 @@ class ViEEncoder bool Init(); + // This function is assumed to be called before any frames are delivered. + void SetSendPayloadRouter(PayloadRouter* send_payload_router); + void SetNetworkTransmissionState(bool is_transmitting); // Returns the id of the owning channel. @@ -201,6 +206,7 @@ class ViEEncoder VideoCodingModule& vcm_; VideoProcessingModule& vpm_; scoped_ptr default_rtp_rtcp_; + PayloadRouter* send_payload_router_; scoped_ptr callback_cs_; scoped_ptr data_cs_; scoped_ptr bitrate_observer_;