Implementing a packet router class, used to route RTP packets to the
sending RTP module for the specified simulcast layer a frame belongs to.
This CL also removes the corresponding functionality from the RTP RTCP
module and fixes lint warnings in the files touched.
BUG=769
TEST=New unittest and manual tests
R=stefan@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/39629004
Cr-Commit-Position: refs/heads/master@{#8267}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8267 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
index bfc8266..8bde0a8 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 <assert.h>
#include <string.h>
+#include <set>
+
#include "webrtc/common_types.h"
#include "webrtc/system_wrappers/interface/logging.h"
#include "webrtc/system_wrappers/interface/trace.h"
@@ -491,74 +493,21 @@
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<ModuleRtpRtcpImpl*>::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<ModuleRtpRtcpImpl*>::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 @@
return !child_modules_.empty();
}
-} // Namespace webrtc
+} // namespace webrtc
diff --git a/webrtc/video_engine/BUILD.gn b/webrtc/video_engine/BUILD.gn
index 889e054..99c16ac 100644
--- a/webrtc/video_engine/BUILD.gn
+++ b/webrtc/video_engine/BUILD.gn
@@ -29,6 +29,8 @@
"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 0000000..f815d13
--- /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<RtpRtcp*>& 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 0000000..3cc0bb0
--- /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 <list>
+#include <vector>
+
+#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<RtpRtcp*>& 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<CriticalSectionWrapper> crit_;
+
+ // Active sending RTP modules, in layer order.
+ std::vector<RtpRtcp*> 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 0000000..b4d20bf
--- /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 <list>
+
+#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<PayloadRouter> payload_router_;
+};
+
+TEST_F(PayloadRouterTest, SendOnOneModule) {
+ MockRtpRtcp rtp;
+ std::list<RtpRtcp*> 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<RtpRtcp*> 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 72e1c64..02726fb 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 62cfd50..8057ca0 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 @@
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 @@
if (paced_sender_) {
rtp_rtcp_->SetStorePacketsStatus(true, nack_history_size_sender_);
}
+ if (sender_) {
+ std::list<RtpRtcp*> 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 @@
module_process_thread_.DeRegisterModule(rtp_rtcp_.get());
module_process_thread_.DeRegisterModule(vcm_);
module_process_thread_.DeRegisterModule(&vie_sync_);
+ send_payload_router_->SetSendingRtpModules(std::list<RtpRtcp*>());
while (simulcast_rtp_rtcp_.size() > 0) {
std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
RtpRtcp* rtp_rtcp = *it;
@@ -322,6 +330,9 @@
// 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<RtpRtcp*>());
if (rtp_rtcp_->Sending() && new_stream) {
restart_rtp = true;
rtp_rtcp_->SetSendingStatus(false);
@@ -480,6 +491,16 @@
(*it)->SetSendingMediaStatus(true);
}
}
+ // Update the packet router with the sending RTP RTCP modules.
+ std::list<RtpRtcp*> active_send_modules;
+ active_send_modules.push_back(rtp_rtcp_.get());
+ for (std::list<RtpRtcp*>::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 @@
}
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 @@
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<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
@@ -1478,6 +1500,10 @@
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 bc91b3a..5640f23 100644
--- a/webrtc/video_engine/vie_channel.h
+++ b/webrtc/video_engine/vie_channel.h
@@ -38,6 +38,7 @@
class EncodedImageCallback;
class I420FrameCallback;
class PacedSender;
+class PayloadRouter;
class ProcessThread;
class ReceiveStatisticsProxy;
class ReportBlockStats;
@@ -301,6 +302,7 @@
// Gets the modules used by the channel.
RtpRtcp* rtp_rtcp();
+ PayloadRouter* send_payload_router();
CallStatsObserver* GetStatsObserver();
@@ -467,6 +469,8 @@
scoped_ptr<RtpRtcp> rtp_rtcp_;
std::list<RtpRtcp*> simulcast_rtp_rtcp_;
std::list<RtpRtcp*> removed_rtp_rtcp_;
+ scoped_ptr<PayloadRouter> 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 aef167f..a2dca8a 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 <vector>
+
#include "webrtc/common.h"
#include "webrtc/engine_configurations.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
@@ -114,6 +116,9 @@
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 @@
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 ca02002..b86c259 100644
--- a/webrtc/video_engine/vie_encoder.cc
+++ b/webrtc/video_engine/vie_encoder.cc
@@ -14,6 +14,7 @@
#include <algorithm>
+#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 @@
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 @@
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 @@
void ViEEncoder::DeliverFrame(int id,
I420VideoFrame* video_frame,
const std::vector<uint32_t>& 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 @@
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 ba7de53..d1723bc 100644
--- a/webrtc/video_engine/vie_encoder.h
+++ b/webrtc/video_engine/vie_encoder.h
@@ -13,6 +13,7 @@
#include <list>
#include <map>
+#include <vector>
#include "webrtc/base/thread_annotations.h"
#include "webrtc/common_types.h"
@@ -32,6 +33,7 @@
class CriticalSectionWrapper;
class EncodedImageCallback;
class PacedSender;
+class PayloadRouter;
class ProcessThread;
class QMVideoSettingsCallback;
class RtpRtcp;
@@ -62,6 +64,9 @@
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 @@
VideoCodingModule& vcm_;
VideoProcessingModule& vpm_;
scoped_ptr<RtpRtcp> default_rtp_rtcp_;
+ PayloadRouter* send_payload_router_;
scoped_ptr<CriticalSectionWrapper> callback_cs_;
scoped_ptr<CriticalSectionWrapper> data_cs_;
scoped_ptr<BitrateObserver> bitrate_observer_;