Adding a send side API for streaming
Review URL: https://webrtc-codereview.appspot.com/1070009
git-svn-id: http://webrtc.googlecode.com/svn/trunk@3457 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/video_engine/include/vie_rtp_rtcp.h b/webrtc/video_engine/include/vie_rtp_rtcp.h
index 73b444a..83b6f57 100644
--- a/webrtc/video_engine/include/vie_rtp_rtcp.h
+++ b/webrtc/video_engine/include/vie_rtp_rtcp.h
@@ -22,7 +22,7 @@
#ifndef WEBRTC_VIDEO_ENGINE_INCLUDE_VIE_RTP_RTCP_H_
#define WEBRTC_VIDEO_ENGINE_INCLUDE_VIE_RTP_RTCP_H_
-#include "common_types.h"
+#include "webrtc/common_types.h"
namespace webrtc {
@@ -199,6 +199,12 @@
const unsigned char payload_typeRED,
const unsigned char payload_typeFEC) = 0;
+ // Enables send side support for delayed video streaming (actual delay will
+ // be exhibited on the receiver side).
+ // Target delay should be set to zero for real-time mode.
+ virtual int EnableSenderStreamingMode(int video_channel,
+ int target_delay_ms) = 0;
+
// This function enables RTCP key frame requests.
virtual int SetKeyFrameRequestMethod(
const int video_channel, const ViEKeyFrameRequestMethod method) = 0;
diff --git a/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc b/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc
index d8bf8aa..64d5c2d 100644
--- a/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc
+++ b/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc
@@ -687,6 +687,21 @@
EXPECT_EQ(0, ViE.rtp_rtcp->SetTransmissionSmoothingStatus(
tbChannel.videoChannel, false));
+ // Streaming Mode.
+ EXPECT_EQ(-1, ViE.rtp_rtcp->EnableSenderStreamingMode(
+ invalid_channel_id, 0));
+ int invalid_delay = -1;
+ EXPECT_EQ(-1, ViE.rtp_rtcp->EnableSenderStreamingMode(
+ tbChannel.videoChannel, invalid_delay));
+ invalid_delay = 15000;
+ EXPECT_EQ(-1, ViE.rtp_rtcp->EnableSenderStreamingMode(
+ tbChannel.videoChannel, invalid_delay));
+ EXPECT_EQ(0, ViE.rtp_rtcp->EnableSenderStreamingMode(
+ tbChannel.videoChannel, 5000));
+ // Real-time mode.
+ EXPECT_EQ(0, ViE.rtp_rtcp->EnableSenderStreamingMode(
+ tbChannel.videoChannel, 0));
+
//***************************************************************
// Testing finished. Tear down Video Engine
//***************************************************************
diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc
index 0c13709..b3e1b7e 100644
--- a/webrtc/video_engine/vie_channel.cc
+++ b/webrtc/video_engine/vie_channel.cc
@@ -35,6 +35,7 @@
const int kMaxDecodeWaitTimeMs = 50;
const int kInvalidRtpExtensionId = 0;
+static const int kMaxTargetDelayMs = 10000;
// Helper class receiving statistics callbacks.
class ChannelStatsObserver : public StatsObserver {
@@ -102,7 +103,8 @@
color_enhancement_(false),
file_recorder_(channel_id),
mtu_(0),
- sender_(sender) {
+ sender_(sender),
+ nack_history_size_sender_(kSendSidePacketHistorySize) {
WEBRTC_TRACE(kTraceMemory, kTraceVideo, ViEId(engine_id, channel_id),
"ViEChannel::ViEChannel(channel_id: %d, engine_id: %d)",
channel_id, engine_id);
@@ -151,7 +153,7 @@
"%s: RTP::SetRTCPStatus failure", __FUNCTION__);
}
if (paced_sender_) {
- if (rtp_rtcp_->SetStorePacketsStatus(true, kSendSidePacketHistorySize) !=
+ if (rtp_rtcp_->SetStorePacketsStatus(true, nack_history_size_sender_) !=
0) {
WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, channel_id_),
"%s:SetStorePacketsStatus failure", __FUNCTION__);
@@ -295,10 +297,10 @@
"%s: RTP::SetRTCPStatus failure", __FUNCTION__);
}
if (nack_method != kNackOff) {
- rtp_rtcp->SetStorePacketsStatus(true, kSendSidePacketHistorySize);
+ rtp_rtcp->SetStorePacketsStatus(true, nack_history_size_sender_);
rtp_rtcp->SetNACKStatus(nack_method, kMaxPacketAgeToNack);
} else if (paced_sender_) {
- rtp_rtcp->SetStorePacketsStatus(true, kSendSidePacketHistorySize);
+ rtp_rtcp->SetStorePacketsStatus(true, nack_history_size_sender_);
}
if (fec_enabled) {
rtp_rtcp->SetGenericFECStatus(fec_enabled, payload_type_red,
@@ -628,7 +630,7 @@
}
WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
"%s: Using NACK method %d", __FUNCTION__, nackMethod);
- rtp_rtcp_->SetStorePacketsStatus(true, kSendSidePacketHistorySize);
+ rtp_rtcp_->SetStorePacketsStatus(true, nack_history_size_sender_);
vcm_.RegisterPacketRequestCallback(this);
@@ -639,7 +641,7 @@
it++) {
RtpRtcp* rtp_rtcp = *it;
rtp_rtcp->SetNACKStatus(nackMethod, kMaxPacketAgeToNack);
- rtp_rtcp->SetStorePacketsStatus(true, kSendSidePacketHistorySize);
+ rtp_rtcp->SetStorePacketsStatus(true, nack_history_size_sender_);
}
} else {
CriticalSectionScoped cs(rtp_rtcp_cs_.get());
@@ -721,6 +723,45 @@
return ProcessFECRequest(enable, payload_typeRED, payload_typeFEC);
}
+int ViEChannel::EnableSenderStreamingMode(int target_delay_ms) {
+ if ((target_delay_ms < 0) || (target_delay_ms > kMaxTargetDelayMs)) {
+ WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
+ "%s: Target streaming delay out of bounds: %d", __FUNCTION__,
+ target_delay_ms);
+ return -1;
+ }
+ if (target_delay_ms == 0) {
+ // Real-time mode.
+ nack_history_size_sender_ = kSendSidePacketHistorySize;
+ vcm_.EnableFrameDropper(true);
+ } else {
+ // The max size of the nack list should be large enough to accommodate the
+ // the number of packets(frames) resulting from the increased delay.
+ // Roughly estimating for ~15 packets per frame @ 30fps.
+ nack_history_size_sender_ = target_delay_ms * 15 * 30 / 1000;
+ // Don't allow a number lower than the default value.
+ if (nack_history_size_sender_ < kSendSidePacketHistorySize) {
+ nack_history_size_sender_ = kSendSidePacketHistorySize;
+ }
+ // Disable external VCM frame-dropper. In streaming mode, we are more
+ // flexible with rate control constraints.
+ vcm_.EnableFrameDropper(false);
+ }
+ // Setting nack_history_size_.
+ // First disabling (forcing free) and then resetting to desired value.
+ if (rtp_rtcp_->SetStorePacketsStatus(false, 0) != 0) {
+ WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
+ "%s:SetStorePacketsStatus failure", __FUNCTION__);
+ return -1;
+ }
+ if (rtp_rtcp_->SetStorePacketsStatus(true, nack_history_size_sender_) != 0) {
+ WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
+ "%s:SetStorePacketsStatus failure", __FUNCTION__);
+ return -1;
+ }
+ return 0;
+}
+
WebRtc_Word32 ViEChannel::SetKeyFrameRequestMethod(
const KeyFrameRequestMethod method) {
WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
diff --git a/webrtc/video_engine/vie_channel.h b/webrtc/video_engine/vie_channel.h
index 4ff77f5..5eec802 100644
--- a/webrtc/video_engine/vie_channel.h
+++ b/webrtc/video_engine/vie_channel.h
@@ -116,6 +116,7 @@
WebRtc_Word32 SetHybridNACKFECStatus(const bool enable,
const unsigned char payload_typeRED,
const unsigned char payload_typeFEC);
+ int EnableSenderStreamingMode(int target_delay_ms);
WebRtc_Word32 SetKeyFrameRequestMethod(const KeyFrameRequestMethod method);
bool EnableRemb(bool enable);
int SetSendTimestampOffsetStatus(bool enable, int id);
@@ -422,6 +423,8 @@
// User set MTU, -1 if not set.
uint16_t mtu_;
const bool sender_;
+
+ int nack_history_size_sender_;
};
} // namespace webrtc
diff --git a/webrtc/video_engine/vie_rtp_rtcp_impl.cc b/webrtc/video_engine/vie_rtp_rtcp_impl.cc
index 0c047d7..7bd6f6d 100644
--- a/webrtc/video_engine/vie_rtp_rtcp_impl.cc
+++ b/webrtc/video_engine/vie_rtp_rtcp_impl.cc
@@ -553,6 +553,33 @@
return 0;
}
+int ViERTP_RTCPImpl::EnableSenderStreamingMode(int video_channel,
+ int target_delay_ms) {
+ WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
+ ViEId(shared_data_->instance_id(), video_channel),
+ "%s(channel: %d, 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's streaming mode settings.
+ if (vie_channel->EnableSenderStreamingMode(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) {
diff --git a/webrtc/video_engine/vie_rtp_rtcp_impl.h b/webrtc/video_engine/vie_rtp_rtcp_impl.h
index 577e085..210afcf 100644
--- a/webrtc/video_engine/vie_rtp_rtcp_impl.h
+++ b/webrtc/video_engine/vie_rtp_rtcp_impl.h
@@ -64,6 +64,8 @@
virtual int SetHybridNACKFECStatus(const int video_channel, const bool enable,
const unsigned char payload_typeRED,
const unsigned char payload_typeFEC);
+ virtual int EnableSenderStreamingMode(int video_channel,
+ int target_delay_ms);
virtual int SetKeyFrameRequestMethod(const int video_channel,
const ViEKeyFrameRequestMethod method);
virtual int SetTMMBRStatus(const int video_channel, const bool enable);