Update stable to r5267.
git-svn-id: http://webrtc.googlecode.com/svn/stable/talk@5268 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/app/webrtc/statscollector.cc b/app/webrtc/statscollector.cc
index 18ab459..b00d19c 100644
--- a/app/webrtc/statscollector.cc
+++ b/app/webrtc/statscollector.cc
@@ -53,6 +53,8 @@
const char StatsReport::kStatsValueNameBytesSent[] = "bytesSent";
const char StatsReport::kStatsValueNameCaptureJitterMs[] =
"googCaptureJitterMs";
+const char StatsReport::kStatsValueNameCaptureQueueDelayMsPerS[] =
+ "googCaptureQueueDelayMsPerS";
const char StatsReport::kStatsValueNameChannelId[] = "googChannelId";
const char StatsReport::kStatsValueNameCodecName[] = "googCodecName";
const char StatsReport::kStatsValueNameComponent[] = "googComponent";
@@ -70,6 +72,8 @@
const char StatsReport::kStatsValueNameEchoReturnLossEnhancement[] =
"googEchoCancellationReturnLossEnhancement";
+const char StatsReport::kStatsValueNameEncodeUsagePercent[] =
+ "googEncodeUsagePercent";
const char StatsReport::kStatsValueNameFingerprint[] = "googFingerprint";
const char StatsReport::kStatsValueNameFingerprintAlgorithm[] =
"googFingerprintAlgorithm";
@@ -298,6 +302,10 @@
report->AddValue(StatsReport::kStatsValueNameAvgEncodeMs, info.avg_encode_ms);
report->AddValue(StatsReport::kStatsValueNameCaptureJitterMs,
info.capture_jitter_ms);
+ report->AddValue(StatsReport::kStatsValueNameCaptureQueueDelayMsPerS,
+ info.capture_queue_delay_ms_per_s);
+ report->AddValue(StatsReport::kStatsValueNameEncodeUsagePercent,
+ info.encode_usage_percent);
}
void ExtractStats(const cricket::BandwidthEstimationInfo& info,
diff --git a/app/webrtc/statstypes.h b/app/webrtc/statstypes.h
index 15210b6..6afc8d7 100644
--- a/app/webrtc/statstypes.h
+++ b/app/webrtc/statstypes.h
@@ -129,7 +129,9 @@
// Internal StatsValue names
static const char kStatsValueNameAvgEncodeMs[];
+ static const char kStatsValueNameEncodeUsagePercent[];
static const char kStatsValueNameCaptureJitterMs[];
+ static const char kStatsValueNameCaptureQueueDelayMsPerS[];
static const char kStatsValueNameCodecName[];
static const char kStatsValueNameEchoCancellationQualityMin[];
static const char kStatsValueNameEchoDelayMedian[];
diff --git a/base/common.h b/base/common.h
index d557639..a76748b 100644
--- a/base/common.h
+++ b/base/common.h
@@ -187,6 +187,10 @@
// (because it won't see this pragma).
#pragma clang diagnostic ignored "-Wc++11-extensions"
#define OVERRIDE override
+#elif defined(__GNUC__) && __cplusplus >= 201103 && \
+ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40700
+// GCC 4.7 supports explicit virtual overrides when C++11 support is enabled.
+#define OVERRIDE override
#else
#define OVERRIDE
#endif
diff --git a/base/sslstreamadapter_unittest.cc b/base/sslstreamadapter_unittest.cc
index e7335be..4b2fd6d 100644
--- a/base/sslstreamadapter_unittest.cc
+++ b/base/sslstreamadapter_unittest.cc
@@ -762,7 +762,7 @@
};
// Test a handshake with small MTU
-TEST_F(SSLStreamAdapterTestDTLS, TestDTLSConnectWithSmallMtu) {
+TEST_F(SSLStreamAdapterTestDTLS, DISABLED_TestDTLSConnectWithSmallMtu) {
MAYBE_SKIP_TEST(HaveDtls);
SetMtu(700);
SetHandshakeWait(20000);
diff --git a/build/isolate.gypi b/build/isolate.gypi
index 83dd502..7b0ac12 100644
--- a/build/isolate.gypi
+++ b/build/isolate.gypi
@@ -71,9 +71,9 @@
'extension': 'isolate',
'inputs': [
# Files that are known to be involved in this step.
- '<(DEPTH)/tools/swarm_client/isolate.py',
- '<(DEPTH)/tools/swarm_client/run_isolated.py',
- '<(DEPTH)/tools/swarm_client/googletest/run_test_cases.py',
+ '<(DEPTH)/tools/swarming_client/isolate.py',
+ '<(DEPTH)/tools/swarming_client/run_isolated.py',
+ '<(DEPTH)/tools/swarming_client/googletest/run_test_cases.py',
# Disable file tracking by the build driver for now. This means the
# project must have the proper build-time dependency for their runtime
@@ -94,7 +94,7 @@
["test_isolation_outdir==''", {
'action': [
'python',
- '<(DEPTH)/tools/swarm_client/isolate.py',
+ '<(DEPTH)/tools/swarming_client/isolate.py',
'<(test_isolation_mode)',
# GYP will eliminate duplicate arguments so '<(PRODUCT_DIR)' cannot
# be provided twice. To work around this behavior, append '/'.
@@ -114,7 +114,7 @@
}, {
'action': [
'python',
- '<(DEPTH)/tools/swarm_client/isolate.py',
+ '<(DEPTH)/tools/swarming_client/isolate.py',
'<(test_isolation_mode)',
'--outdir', '<(test_isolation_outdir)',
# See comment above.
diff --git a/examples/android/project.properties b/examples/android/project.properties
index bc163b0..8459f9b 100644
--- a/examples/android/project.properties
+++ b/examples/android/project.properties
@@ -11,6 +11,6 @@
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
-target=android-17
+target=android-19
java.compilerargs=-Xlint:all -Werror
diff --git a/libjingle_media_unittest.isolate b/libjingle_media_unittest.isolate
index 4c4ee31..36b50b5 100644
--- a/libjingle_media_unittest.isolate
+++ b/libjingle_media_unittest.isolate
@@ -30,7 +30,6 @@
'variables': {
'command': [
'../testing/test_env.py',
- '../tools/swarm_client/googletest/run_test_cases.py',
'<(PRODUCT_DIR)/libjingle_media_unittest<(EXECUTABLE_SUFFIX)',
],
'isolate_dependency_tracked': [
@@ -39,7 +38,7 @@
'<(PRODUCT_DIR)/libjingle_media_unittest<(EXECUTABLE_SUFFIX)',
],
'isolate_dependency_untracked': [
- '../tools/swarm_client/',
+ '../tools/swarming_client/',
],
},
}],
diff --git a/libjingle_p2p_unittest.isolate b/libjingle_p2p_unittest.isolate
index 848f234..b5ad4ff 100644
--- a/libjingle_p2p_unittest.isolate
+++ b/libjingle_p2p_unittest.isolate
@@ -30,7 +30,6 @@
'variables': {
'command': [
'../testing/test_env.py',
- '../tools/swarm_client/googletest/run_test_cases.py',
'<(PRODUCT_DIR)/libjingle_p2p_unittest<(EXECUTABLE_SUFFIX)',
],
'isolate_dependency_tracked': [
@@ -38,7 +37,7 @@
'<(PRODUCT_DIR)/libjingle_p2p_unittest<(EXECUTABLE_SUFFIX)',
],
'isolate_dependency_untracked': [
- '../tools/swarm_client/',
+ '../tools/swarming_client/',
],
},
}],
diff --git a/libjingle_peerconnection_unittest.isolate b/libjingle_peerconnection_unittest.isolate
index 660ffd5..e7dd687 100644
--- a/libjingle_peerconnection_unittest.isolate
+++ b/libjingle_peerconnection_unittest.isolate
@@ -30,7 +30,6 @@
'variables': {
'command': [
'../testing/test_env.py',
- '../tools/swarm_client/googletest/run_test_cases.py',
'<(PRODUCT_DIR)/libjingle_peerconnection_unittest<(EXECUTABLE_SUFFIX)',
],
'isolate_dependency_tracked': [
@@ -38,7 +37,7 @@
'<(PRODUCT_DIR)/libjingle_peerconnection_unittest<(EXECUTABLE_SUFFIX)',
],
'isolate_dependency_untracked': [
- '../tools/swarm_client/',
+ '../tools/swarming_client/',
],
},
}],
diff --git a/libjingle_sound_unittest.isolate b/libjingle_sound_unittest.isolate
index 6da7d88..7166337 100644
--- a/libjingle_sound_unittest.isolate
+++ b/libjingle_sound_unittest.isolate
@@ -30,7 +30,6 @@
'variables': {
'command': [
'../testing/test_env.py',
- '../tools/swarm_client/googletest/run_test_cases.py',
'<(PRODUCT_DIR)/libjingle_sound_unittest<(EXECUTABLE_SUFFIX)',
],
'isolate_dependency_tracked': [
@@ -38,7 +37,7 @@
'<(PRODUCT_DIR)/libjingle_sound_unittest<(EXECUTABLE_SUFFIX)',
],
'isolate_dependency_untracked': [
- '../tools/swarm_client/',
+ '../tools/swarming_client/',
],
},
}],
diff --git a/libjingle_tests.gyp b/libjingle_tests.gyp
index a88942f..7bfea59 100755
--- a/libjingle_tests.gyp
+++ b/libjingle_tests.gyp
@@ -88,6 +88,7 @@
'media/base/testutils.cc',
'media/base/testutils.h',
'media/devices/fakedevicemanager.h',
+ 'media/webrtc/dummyinstantiation.cc',
'media/webrtc/fakewebrtccommon.h',
'media/webrtc/fakewebrtcdeviceinfo.h',
'media/webrtc/fakewebrtcvcmfactory.h',
diff --git a/libjingle_unittest.isolate b/libjingle_unittest.isolate
index efb8625..e678af0 100644
--- a/libjingle_unittest.isolate
+++ b/libjingle_unittest.isolate
@@ -30,7 +30,6 @@
'variables': {
'command': [
'../testing/test_env.py',
- '../tools/swarm_client/googletest/run_test_cases.py',
'<(PRODUCT_DIR)/libjingle_unittest<(EXECUTABLE_SUFFIX)',
],
'isolate_dependency_tracked': [
@@ -38,7 +37,7 @@
'<(PRODUCT_DIR)/libjingle_unittest<(EXECUTABLE_SUFFIX)',
],
'isolate_dependency_untracked': [
- '../tools/swarm_client/',
+ '../tools/swarming_client/',
],
},
}],
diff --git a/media/base/filemediaengine.cc b/media/base/filemediaengine.cc
index e5183f6..80e9729 100644
--- a/media/base/filemediaengine.cc
+++ b/media/base/filemediaengine.cc
@@ -83,7 +83,8 @@
}
}
- return new FileVoiceChannel(input_file_stream, output_file_stream);
+ return new FileVoiceChannel(input_file_stream, output_file_stream,
+ rtp_sender_thread_);
}
VideoMediaChannel* FileMediaEngine::CreateVideoChannel(
@@ -113,18 +114,19 @@
}
}
- return new FileVideoChannel(input_file_stream, output_file_stream);
+ return new FileVideoChannel(input_file_stream, output_file_stream,
+ rtp_sender_thread_);
}
///////////////////////////////////////////////////////////////////////////
// Definition of RtpSenderReceiver.
///////////////////////////////////////////////////////////////////////////
-class RtpSenderReceiver
- : public talk_base::Thread, public talk_base::MessageHandler {
+class RtpSenderReceiver : public talk_base::MessageHandler {
public:
RtpSenderReceiver(MediaChannel* channel,
talk_base::StreamInterface* input_file_stream,
- talk_base::StreamInterface* output_file_stream);
+ talk_base::StreamInterface* output_file_stream,
+ talk_base::Thread* sender_thread);
virtual ~RtpSenderReceiver();
// Called by media channel. Context: media channel thread.
@@ -149,6 +151,8 @@
talk_base::scoped_ptr<talk_base::StreamInterface> output_stream_;
talk_base::scoped_ptr<RtpDumpLoopReader> rtp_dump_reader_;
talk_base::scoped_ptr<RtpDumpWriter> rtp_dump_writer_;
+ talk_base::Thread* sender_thread_;
+ bool own_sender_thread_;
// RTP dump packet read from the input stream.
RtpDumpPacket rtp_dump_packet_;
uint32 start_send_time_;
@@ -165,34 +169,48 @@
RtpSenderReceiver::RtpSenderReceiver(
MediaChannel* channel,
talk_base::StreamInterface* input_file_stream,
- talk_base::StreamInterface* output_file_stream)
+ talk_base::StreamInterface* output_file_stream,
+ talk_base::Thread* sender_thread)
: media_channel_(channel),
+ input_stream_(input_file_stream),
+ output_stream_(output_file_stream),
sending_(false),
first_packet_(true) {
- input_stream_.reset(input_file_stream);
+ if (sender_thread == NULL) {
+ sender_thread_ = new talk_base::Thread();
+ own_sender_thread_ = true;
+ } else {
+ sender_thread_ = sender_thread;
+ own_sender_thread_ = false;
+ }
+
if (input_stream_) {
rtp_dump_reader_.reset(new RtpDumpLoopReader(input_stream_.get()));
// Start the sender thread, which reads rtp dump records, waits based on
// the record timestamps, and sends the RTP packets to the network.
- Thread::Start();
+ if (own_sender_thread_) {
+ sender_thread_->Start();
+ }
}
// Create a rtp dump writer for the output RTP dump stream.
- output_stream_.reset(output_file_stream);
if (output_stream_) {
rtp_dump_writer_.reset(new RtpDumpWriter(output_stream_.get()));
}
}
RtpSenderReceiver::~RtpSenderReceiver() {
- Stop();
+ if (own_sender_thread_) {
+ sender_thread_->Stop();
+ delete sender_thread_;
+ }
}
bool RtpSenderReceiver::SetSend(bool send) {
bool was_sending = sending_;
sending_ = send;
if (!was_sending && sending_) {
- PostDelayed(0, this); // Wake up the send thread.
+ sender_thread_->PostDelayed(0, this); // Wake up the send thread.
start_send_time_ = talk_base::Time();
}
return true;
@@ -216,7 +234,6 @@
// to sleep until SetSend(true) wakes it up.
return;
}
-
if (!first_packet_) {
// Send the previously read packet.
SendRtpPacket(&rtp_dump_packet_.data[0], rtp_dump_packet_.data.size());
@@ -226,9 +243,9 @@
int wait = talk_base::TimeUntil(
start_send_time_ + rtp_dump_packet_.elapsed_time);
wait = talk_base::_max(0, wait);
- PostDelayed(wait, this);
+ sender_thread_->PostDelayed(wait, this);
} else {
- Quit();
+ sender_thread_->Quit();
}
}
@@ -262,10 +279,12 @@
///////////////////////////////////////////////////////////////////////////
FileVoiceChannel::FileVoiceChannel(
talk_base::StreamInterface* input_file_stream,
- talk_base::StreamInterface* output_file_stream)
+ talk_base::StreamInterface* output_file_stream,
+ talk_base::Thread* rtp_sender_thread)
: send_ssrc_(0),
rtp_sender_receiver_(new RtpSenderReceiver(this, input_file_stream,
- output_file_stream)) {}
+ output_file_stream,
+ rtp_sender_thread)) {}
FileVoiceChannel::~FileVoiceChannel() {}
@@ -305,10 +324,12 @@
///////////////////////////////////////////////////////////////////////////
FileVideoChannel::FileVideoChannel(
talk_base::StreamInterface* input_file_stream,
- talk_base::StreamInterface* output_file_stream)
+ talk_base::StreamInterface* output_file_stream,
+ talk_base::Thread* rtp_sender_thread)
: send_ssrc_(0),
rtp_sender_receiver_(new RtpSenderReceiver(this, input_file_stream,
- output_file_stream)) {}
+ output_file_stream,
+ rtp_sender_thread)) {}
FileVideoChannel::~FileVideoChannel() {}
diff --git a/media/base/filemediaengine.h b/media/base/filemediaengine.h
index 9cdfe83..129af9c 100644
--- a/media/base/filemediaengine.h
+++ b/media/base/filemediaengine.h
@@ -50,7 +50,7 @@
// only the RTP dump packets. TODO(whyuan): Enable RTCP packets.
class FileMediaEngine : public MediaEngineInterface {
public:
- FileMediaEngine() {}
+ FileMediaEngine() : rtp_sender_thread_(NULL) {}
virtual ~FileMediaEngine() {}
// Set the file name of the input or output RTP dump for voice or video.
@@ -159,6 +159,10 @@
return signal_state_change_;
}
+ void set_rtp_sender_thread(talk_base::Thread* thread) {
+ rtp_sender_thread_ = thread;
+ }
+
private:
std::string voice_input_filename_;
std::string voice_output_filename_;
@@ -170,6 +174,7 @@
std::vector<RtpHeaderExtension> video_rtp_header_extensions_;
sigslot::repeater2<VideoCapturer*, CaptureState>
signal_state_change_;
+ talk_base::Thread* rtp_sender_thread_;
DISALLOW_COPY_AND_ASSIGN(FileMediaEngine);
};
@@ -179,7 +184,8 @@
class FileVoiceChannel : public VoiceMediaChannel {
public:
FileVoiceChannel(talk_base::StreamInterface* input_file_stream,
- talk_base::StreamInterface* output_file_stream);
+ talk_base::StreamInterface* output_file_stream,
+ talk_base::Thread* rtp_sender_thread);
virtual ~FileVoiceChannel();
// Implement pure virtual methods of VoiceMediaChannel.
@@ -255,7 +261,8 @@
class FileVideoChannel : public VideoMediaChannel {
public:
FileVideoChannel(talk_base::StreamInterface* input_file_stream,
- talk_base::StreamInterface* output_file_stream);
+ talk_base::StreamInterface* output_file_stream,
+ talk_base::Thread* rtp_sender_thread);
virtual ~FileVideoChannel();
// Implement pure virtual methods of VideoMediaChannel.
diff --git a/media/base/filemediaengine_unittest.cc b/media/base/filemediaengine_unittest.cc
index a72e0dc..7ba96a2 100644
--- a/media/base/filemediaengine_unittest.cc
+++ b/media/base/filemediaengine_unittest.cc
@@ -136,6 +136,7 @@
engine_->set_voice_output_filename(voice_out);
engine_->set_video_input_filename(video_in);
engine_->set_video_output_filename(video_out);
+ engine_->set_rtp_sender_thread(talk_base::Thread::Current());
voice_channel_.reset(engine_->CreateChannel());
video_channel_.reset(engine_->CreateVideoChannel(NULL));
diff --git a/media/base/mediachannel.h b/media/base/mediachannel.h
index d7e7192..9e1ea9d 100644
--- a/media/base/mediachannel.h
+++ b/media/base/mediachannel.h
@@ -298,7 +298,6 @@
adapt_view_switch.SetFrom(change.adapt_view_switch);
video_adapt_third.SetFrom(change.video_adapt_third);
video_noise_reduction.SetFrom(change.video_noise_reduction);
- video_three_layers.SetFrom(change.video_three_layers);
video_one_layer_screencast.SetFrom(change.video_one_layer_screencast);
video_high_bitrate.SetFrom(change.video_high_bitrate);
video_watermark.SetFrom(change.video_watermark);
@@ -327,7 +326,6 @@
adapt_view_switch == o.adapt_view_switch &&
video_adapt_third == o.video_adapt_third &&
video_noise_reduction == o.video_noise_reduction &&
- video_three_layers == o.video_three_layers &&
video_one_layer_screencast == o.video_one_layer_screencast &&
video_high_bitrate == o.video_high_bitrate &&
video_watermark == o.video_watermark &&
@@ -356,7 +354,6 @@
ost << ToStringIfSet("adapt view switch", adapt_view_switch);
ost << ToStringIfSet("video adapt third", video_adapt_third);
ost << ToStringIfSet("noise reduction", video_noise_reduction);
- ost << ToStringIfSet("3 layers", video_three_layers);
ost << ToStringIfSet("1 layer screencast", video_one_layer_screencast);
ost << ToStringIfSet("high bitrate", video_high_bitrate);
ost << ToStringIfSet("watermark", video_watermark);
@@ -391,8 +388,6 @@
Settable<bool> video_adapt_third;
// Enable denoising?
Settable<bool> video_noise_reduction;
- // Experimental: Enable multi layer?
- Settable<bool> video_three_layers;
// Experimental: Enable one layer screencast?
Settable<bool> video_one_layer_screencast;
// Experimental: Enable WebRtc higher bitrate?
@@ -776,7 +771,9 @@
preferred_bitrate(0),
adapt_reason(0),
capture_jitter_ms(0),
- avg_encode_ms(0) {
+ avg_encode_ms(0),
+ encode_usage_percent(0),
+ capture_queue_delay_ms_per_s(0) {
}
std::vector<SsrcGroup> ssrc_groups;
@@ -792,6 +789,8 @@
int adapt_reason;
int capture_jitter_ms;
int avg_encode_ms;
+ int encode_usage_percent;
+ int capture_queue_delay_ms_per_s;
};
struct VideoReceiverInfo : public MediaReceiverInfo {
diff --git a/media/base/videoadapter.cc b/media/base/videoadapter.cc
index 20114fb..22b1f7d 100644
--- a/media/base/videoadapter.cc
+++ b/media/base/videoadapter.cc
@@ -165,8 +165,8 @@
frames_(0),
adapted_frames_(0),
adaption_changes_(0),
- previous_width(0),
- previous_height(0),
+ previous_width_(0),
+ previous_height_(0),
black_output_(false),
is_black_(false),
interval_next_frame_(0) {
@@ -240,11 +240,11 @@
// TODO(fbarchard): Add AdaptFrameRate function that only drops frames but
// not resolution.
bool VideoAdapter::AdaptFrame(const VideoFrame* in_frame,
- const VideoFrame** out_frame) {
- talk_base::CritScope cs(&critical_section_);
+ VideoFrame** out_frame) {
if (!in_frame || !out_frame) {
return false;
}
+ talk_base::CritScope cs(&critical_section_);
++frames_;
// Update input to actual frame dimensions.
@@ -306,8 +306,8 @@
// resolution changes as well. Consider dropping the statistics into their
// own class which could be queried publically.
bool changed = false;
- if (previous_width && (previous_width != (*out_frame)->GetWidth() ||
- previous_height != (*out_frame)->GetHeight())) {
+ if (previous_width_ && (previous_width_ != (*out_frame)->GetWidth() ||
+ previous_height_ != (*out_frame)->GetHeight())) {
show = true;
++adaption_changes_;
changed = true;
@@ -325,8 +325,8 @@
<< "x" << (*out_frame)->GetHeight()
<< " Changed: " << (changed ? "true" : "false");
}
- previous_width = (*out_frame)->GetWidth();
- previous_height = (*out_frame)->GetHeight();
+ previous_width_ = (*out_frame)->GetWidth();
+ previous_height_ = (*out_frame)->GetHeight();
return true;
}
@@ -376,7 +376,7 @@
///////////////////////////////////////////////////////////////////////
// Implementation of CoordinatedVideoAdapter
CoordinatedVideoAdapter::CoordinatedVideoAdapter()
- : cpu_adaptation_(false),
+ : cpu_adaptation_(true),
cpu_smoothing_(false),
gd_adaptation_(true),
view_adaptation_(true),
diff --git a/media/base/videoadapter.h b/media/base/videoadapter.h
index 38a8c9d..12be4fa 100644
--- a/media/base/videoadapter.h
+++ b/media/base/videoadapter.h
@@ -62,7 +62,7 @@
// successfully. Return false otherwise.
// output_frame_ is owned by the VideoAdapter that has the best knowledge on
// the output frame.
- bool AdaptFrame(const VideoFrame* in_frame, const VideoFrame** out_frame);
+ bool AdaptFrame(const VideoFrame* in_frame, VideoFrame** out_frame);
void set_scale_third(bool enable) {
LOG(LS_INFO) << "Video Adapter third scaling is now "
@@ -90,8 +90,8 @@
int frames_; // Number of input frames.
int adapted_frames_; // Number of frames scaled.
int adaption_changes_; // Number of changes in scale factor.
- size_t previous_width; // Previous adapter output width.
- size_t previous_height; // Previous adapter output height.
+ size_t previous_width_; // Previous adapter output width.
+ size_t previous_height_; // Previous adapter output height.
bool black_output_; // Flag to tell if we need to black output_frame_.
bool is_black_; // Flag to tell if output_frame_ is currently black.
int64 interval_next_frame_;
diff --git a/media/base/videocapturer.cc b/media/base/videocapturer.cc
index 0d2a20f..26fcfa9 100644
--- a/media/base/videocapturer.cc
+++ b/media/base/videocapturer.cc
@@ -475,14 +475,25 @@
<< desired_width << " x " << desired_height;
return;
}
- if (!muted_ && !ApplyProcessors(&i420_frame)) {
+
+ VideoFrame* adapted_frame = &i420_frame;
+ if (!SignalAdaptFrame.is_empty() && !IsScreencast()) {
+ VideoFrame* out_frame = NULL;
+ SignalAdaptFrame(this, adapted_frame, &out_frame);
+ if (!out_frame) {
+ return; // VideoAdapter dropped the frame.
+ }
+ adapted_frame = out_frame;
+ }
+
+ if (!muted_ && !ApplyProcessors(adapted_frame)) {
// Processor dropped the frame.
return;
}
if (muted_) {
- i420_frame.SetToBlack();
+ adapted_frame->SetToBlack();
}
- SignalVideoFrame(this, &i420_frame);
+ SignalVideoFrame(this, adapted_frame);
#endif // VIDEO_FRAME_NAME
}
diff --git a/media/base/videocapturer.h b/media/base/videocapturer.h
index 933fc82..2bd68bc 100644
--- a/media/base/videocapturer.h
+++ b/media/base/videocapturer.h
@@ -255,6 +255,11 @@
// Signal the captured frame to downstream.
sigslot::signal2<VideoCapturer*, const CapturedFrame*,
sigslot::multi_threaded_local> SignalFrameCaptured;
+ // If slots are connected to SignalAdaptFrame, this signals with parameters
+ // of this capturer instance, the input video frame and output frame
+ // pointer, respectively.
+ sigslot::signal3<VideoCapturer*, const VideoFrame*, VideoFrame**,
+ sigslot::multi_threaded_local> SignalAdaptFrame;
// Signal the captured frame converted to I420 to downstream.
sigslot::signal2<VideoCapturer*, const VideoFrame*,
sigslot::multi_threaded_local> SignalVideoFrame;
diff --git a/media/base/videoengine_unittest.h b/media/base/videoengine_unittest.h
index f50a765..95d8f6c 100644
--- a/media/base/videoengine_unittest.h
+++ b/media/base/videoengine_unittest.h
@@ -54,6 +54,12 @@
EXPECT_EQ((h), (r).height()); \
EXPECT_EQ(0, (r).errors()); \
+#define EXPECT_GT_FRAME_ON_RENDERER_WAIT(r, c, w, h, t) \
+ EXPECT_TRUE_WAIT((r).num_rendered_frames() >= (c) && \
+ (w) == (r).width() && \
+ (h) == (r).height(), (t)); \
+ EXPECT_EQ(0, (r).errors()); \
+
static const uint32 kTimeout = 5000U;
static const uint32 kSsrc = 1234u;
static const uint32 kRtxSsrc = 4321u;
@@ -1002,7 +1008,8 @@
EXPECT_GE(2, NumRtpPackets());
uint32 ssrc = 0;
size_t last_packet = NumRtpPackets() - 1;
- talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(last_packet));
+ talk_base::scoped_ptr<const talk_base::Buffer>
+ p(GetRtpPacket(static_cast<int>(last_packet)));
ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
EXPECT_EQ(kSsrc, ssrc);
@@ -1019,7 +1026,7 @@
EXPECT_TRUE_WAIT(NumRtpPackets() > rtp_packets, kTimeout);
last_packet = NumRtpPackets() - 1;
- p.reset(GetRtpPacket(last_packet));
+ p.reset(GetRtpPacket(static_cast<int>(last_packet)));
ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
EXPECT_EQ(789u, ssrc);
}
@@ -1167,7 +1174,11 @@
EXPECT_TRUE(channel_->SetRenderer(kSsrc, &renderer1));
EXPECT_TRUE(SendFrame());
- EXPECT_FRAME_ON_RENDERER_WAIT(
+ // Because the default channel is used, RemoveRecvStream above is not going
+ // to delete the channel. As a result the engine will continue to receive
+ // and decode the 3 frames sent above. So it is possible we will receive
+ // some (e.g. 1) of these 3 frames after the renderer is set again.
+ EXPECT_GT_FRAME_ON_RENDERER_WAIT(
renderer1, 2, DefaultCodec().width, DefaultCodec().height, kTimeout);
}
@@ -1279,16 +1290,15 @@
EXPECT_FRAME_WAIT(1, 640, 400, kTimeout);
// Remove the capturer.
EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
+ // Wait for one black frame for removing the capturer.
+ EXPECT_FRAME_WAIT(2, 640, 400, kTimeout);
+
// No capturer was added, so this RemoveCapturer should
// fail.
EXPECT_FALSE(channel_->SetCapturer(kSsrc, NULL));
- // Wait for frames to stop flowing.
talk_base::Thread::Current()->ProcessMessages(300);
- int num_frames = renderer_.num_rendered_frames();
- // Wait to make sure no more frames are sent
- WAIT(renderer_.num_rendered_frames() != num_frames, 300);
// Verify no more frames were sent.
- EXPECT_EQ(num_frames, renderer_.num_rendered_frames());
+ EXPECT_EQ(2, renderer_.num_rendered_frames());
}
// Tests that we can add and remove capturer as unique sources.
@@ -1375,10 +1385,8 @@
EXPECT_EQ(0, renderer.num_rendered_frames());
EXPECT_TRUE(SendFrame());
- EXPECT_TRUE_WAIT(renderer.num_rendered_frames() >= 1 &&
- codec.width == renderer.width() &&
- codec.height == renderer.height(), kTimeout);
- EXPECT_EQ(0, renderer.errors());
+ EXPECT_GT_FRAME_ON_RENDERER_WAIT(
+ renderer, 1, codec.width, codec.height, kTimeout);
// Registering an external capturer is currently the same as screen casting
// (update the test when this changes).
@@ -1396,9 +1404,8 @@
EXPECT_TRUE(capturer->CaptureCustomFrame(kWidth, kHeight,
cricket::FOURCC_ARGB));
EXPECT_TRUE(capturer->CaptureFrame());
- EXPECT_TRUE_WAIT(renderer.num_rendered_frames() >= 2 &&
- kScaledWidth == renderer.width() &&
- kScaledHeight == renderer.height(), kTimeout);
+ EXPECT_GT_FRAME_ON_RENDERER_WAIT(
+ renderer, 2, kScaledWidth, kScaledHeight, kTimeout);
EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
}
diff --git a/media/base/videoframe_unittest.h b/media/base/videoframe_unittest.h
index 42485f1..d7be7e3 100644
--- a/media/base/videoframe_unittest.h
+++ b/media/base/videoframe_unittest.h
@@ -527,7 +527,7 @@
kWidth, kHeight));
EXPECT_TRUE(LoadFrame(y, buf_size, cricket::FOURCC_I422,
kWidth, kHeight, &frame2));
- EXPECT_TRUE(IsEqual(frame1, frame2, 0));
+ EXPECT_TRUE(IsEqual(frame1, frame2, 1));
}
// Test constructing an image from a YUY2 buffer.
@@ -1861,7 +1861,7 @@
kWidth, kHeight, kWidth, kHeight,
y,
out_size, 1, 1, 0, 0, cricket::ROTATION_0));
- EXPECT_TRUE(IsEqual(frame1, frame2, 0));
+ EXPECT_TRUE(IsEqual(frame1, frame2, 1));
}
#define TEST_TOBYR(NAME, BAYER) \
diff --git a/media/webrtc/dummyinstantiation.cc b/media/webrtc/dummyinstantiation.cc
new file mode 100644
index 0000000..7d27967
--- /dev/null
+++ b/media/webrtc/dummyinstantiation.cc
@@ -0,0 +1,37 @@
+/*
+ * libjingle
+ * Copyright 2013 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/media/webrtc/fakewebrtcvideoengine.h"
+#include "talk/media/webrtc/fakewebrtcvoiceengine.h"
+
+static void EnsureAPIMatch() {
+ new cricket::FakeWebRtcVoiceEngine(NULL, 0);
+ new cricket::FakeWebRtcVideoDecoder();
+ new cricket::FakeWebRtcVideoEncoder();
+ new cricket::FakeWebRtcVideoEngine(NULL, 0);
+ new cricket::FakeWebRtcVideoEngine::Capturer();
+}
diff --git a/media/webrtc/fakewebrtcvideoengine.h b/media/webrtc/fakewebrtcvideoengine.h
index b81d04b..850451b 100644
--- a/media/webrtc/fakewebrtcvideoengine.h
+++ b/media/webrtc/fakewebrtcvideoengine.h
@@ -33,6 +33,7 @@
#include <vector>
#include "talk/base/basictypes.h"
+#include "talk/base/gunit.h"
#include "talk/base/stringutils.h"
#include "talk/media/base/codec.h"
#include "talk/media/webrtc/fakewebrtccommon.h"
@@ -338,12 +339,14 @@
};
class Capturer : public webrtc::ViEExternalCapture {
public:
- Capturer() : channel_id_(-1), denoising_(false), last_capture_time_(0) { }
+ Capturer() : channel_id_(-1), denoising_(false),
+ last_capture_time_(0), incoming_frame_num_(0) { }
int channel_id() const { return channel_id_; }
void set_channel_id(int channel_id) { channel_id_ = channel_id; }
bool denoising() const { return denoising_; }
void set_denoising(bool denoising) { denoising_ = denoising; }
- int64 last_capture_time() { return last_capture_time_; }
+ int64 last_capture_time() const { return last_capture_time_; }
+ int incoming_frame_num() const { return incoming_frame_num_; }
// From ViEExternalCapture
virtual int IncomingFrame(unsigned char* videoFrame,
@@ -358,6 +361,7 @@
const webrtc::ViEVideoFrameI420& video_frame,
unsigned long long captureTime) {
last_capture_time_ = captureTime;
+ ++incoming_frame_num_;
return 0;
}
@@ -365,6 +369,7 @@
int channel_id_;
bool denoising_;
int64 last_capture_time_;
+ int incoming_frame_num_;
};
FakeWebRtcVideoEngine(const cricket::VideoCodec* const* codecs,
@@ -407,6 +412,16 @@
int GetLastCapturer() const { return last_capturer_; }
int GetNumCapturers() const { return static_cast<int>(capturers_.size()); }
+ int GetIncomingFrameNum(int channel_id) const {
+ for (std::map<int, Capturer*>::const_iterator iter = capturers_.begin();
+ iter != capturers_.end(); ++iter) {
+ Capturer* capturer = iter->second;
+ if (capturer->channel_id() == channel_id) {
+ return capturer->incoming_frame_num();
+ }
+ }
+ return -1;
+ }
void set_fail_alloc_capturer(bool fail_alloc_capturer) {
fail_alloc_capturer_ = fail_alloc_capturer;
}
@@ -626,7 +641,7 @@
WEBRTC_STUB(RegisterCpuOveruseObserver,
(int channel, webrtc::CpuOveruseObserver* observer));
#ifdef USE_WEBRTC_DEV_BRANCH
- WEBRTC_STUB(CpuOveruseMeasures, (int, int*, int*));
+ WEBRTC_STUB(CpuOveruseMeasures, (int, int*, int*, int*, int*));
#endif
WEBRTC_STUB(ConnectAudioChannel, (const int, const int));
WEBRTC_STUB(DisconnectAudioChannel, (const int));
@@ -745,9 +760,7 @@
WEBRTC_STUB(WaitForFirstKeyFrame, (const int, const bool));
WEBRTC_STUB(StartDebugRecording, (int, const char*));
WEBRTC_STUB(StopDebugRecording, (int));
-#ifdef USE_WEBRTC_DEV_BRANCH
WEBRTC_VOID_STUB(SuspendBelowMinBitrate, (int));
-#endif
// webrtc::ViECapture
WEBRTC_STUB(NumberOfCaptureDevices, ());
@@ -1022,6 +1035,9 @@
channels_[channel]->rtp_absolute_send_time_receive_id_ = (enable) ? id : 0;
return 0;
}
+#ifdef USE_WEBRTC_DEV_BRANCH
+ WEBRTC_STUB(SetRtcpXrRrtrStatus, (int, bool));
+#endif
WEBRTC_FUNC(SetTransmissionSmoothingStatus, (int channel, bool enable)) {
WEBRTC_CHECK_CHANNEL(channel);
channels_[channel]->transmission_smoothing_ = enable;
@@ -1033,14 +1049,12 @@
unsigned int&, unsigned int&, unsigned int&, int&));
WEBRTC_STUB_CONST(GetRTPStatistics, (const int, unsigned int&, unsigned int&,
unsigned int&, unsigned int&));
-#ifdef USE_WEBRTC_DEV_BRANCH
WEBRTC_STUB_CONST(GetReceiveChannelRtcpStatistics, (const int,
webrtc::RtcpStatistics&, int&));
WEBRTC_STUB_CONST(GetSendChannelRtcpStatistics, (const int,
webrtc::RtcpStatistics&, int&));
WEBRTC_STUB_CONST(GetRtpStatistics, (const int, webrtc::StreamDataCounters&,
webrtc::StreamDataCounters&));
-#endif
WEBRTC_FUNC_CONST(GetBandwidthUsage, (const int channel,
unsigned int& total_bitrate, unsigned int& video_bitrate,
unsigned int& fec_bitrate, unsigned int& nack_bitrate)) {
@@ -1083,7 +1097,6 @@
}
return 0;
}
-#ifdef USE_WEBRTC_DEV_BRANCH
WEBRTC_STUB(RegisterSendChannelRtcpStatisticsCallback,
(int, webrtc::RtcpStatisticsCallback*));
WEBRTC_STUB(DeregisterSendChannelRtcpStatisticsCallback,
@@ -1108,7 +1121,6 @@
(int, webrtc::FrameCountObserver*));
WEBRTC_STUB(DeregisterSendFrameCountObserver,
(int, webrtc::FrameCountObserver*));
-#endif
WEBRTC_STUB(StartRTPDump, (const int, const char*, webrtc::RTPDirections));
WEBRTC_STUB(StopRTPDump, (const int, webrtc::RTPDirections));
diff --git a/media/webrtc/fakewebrtcvoiceengine.h b/media/webrtc/fakewebrtcvoiceengine.h
index ece0339..809816b 100644
--- a/media/webrtc/fakewebrtcvoiceengine.h
+++ b/media/webrtc/fakewebrtcvoiceengine.h
@@ -34,6 +34,7 @@
#include "talk/base/basictypes.h"
+#include "talk/base/gunit.h"
#include "talk/base/stringutils.h"
#include "talk/media/base/codec.h"
#include "talk/media/base/voiceprocessor.h"
@@ -181,7 +182,7 @@
}
return -1;
}
- int GetNumChannels() const { return channels_.size(); }
+ int GetNumChannels() const { return static_cast<int>(channels_.size()); }
bool GetPlayout(int channel) {
return channels_[channel]->playout;
}
@@ -298,14 +299,12 @@
WEBRTC_FUNC(CreateChannel, ()) {
return AddChannel(false);
}
-#ifdef USE_WEBRTC_DEV_BRANCH
WEBRTC_FUNC(CreateChannel, (const webrtc::Config& config)) {
talk_base::scoped_ptr<webrtc::AudioCodingModule> acm(
config.Get<webrtc::AudioCodingModuleFactory>().Create(0));
return AddChannel(strcmp(acm->Version(), webrtc::kExperimentalAcmVersion)
== 0);
}
-#endif
WEBRTC_FUNC(DeleteChannel, (int channel)) {
WEBRTC_CHECK_CHANNEL(channel);
delete channels_[channel];
@@ -917,6 +916,9 @@
WEBRTC_STUB(GetEcDelayMetrics, (int& delay_median, int& delay_std));
WEBRTC_STUB(StartDebugRecording, (const char* fileNameUTF8));
+#ifdef USE_WEBRTC_DEV_BRANCH
+ WEBRTC_STUB(StartDebugRecording, (FILE* handle));
+#endif
WEBRTC_STUB(StopDebugRecording, ());
WEBRTC_FUNC(SetTypingDetectionStatus, (bool enable)) {
diff --git a/media/webrtc/webrtcvideoengine.cc b/media/webrtc/webrtcvideoengine.cc
index 397deb0..d6fabdb 100644
--- a/media/webrtc/webrtcvideoengine.cc
+++ b/media/webrtc/webrtcvideoengine.cc
@@ -228,9 +228,8 @@
}
virtual int DeliverFrame(unsigned char* buffer, int buffer_size,
- uint32_t time_stamp, int64_t render_time
- , void* handle
- ) {
+ uint32_t time_stamp, int64_t render_time,
+ void* handle) {
talk_base::CritScope cs(&crit_);
frame_rate_tracker_.Update(1);
if (renderer_ == NULL) {
@@ -633,10 +632,6 @@
}
}
- bool AdaptFrame(const VideoFrame* in_frame, const VideoFrame** out_frame) {
- *out_frame = NULL;
- return video_adapter_->AdaptFrame(in_frame, out_frame);
- }
int CurrentAdaptReason() const {
return video_adapter_->adapt_reason();
}
@@ -677,9 +672,18 @@
// video capturer.
video_adapter_->SetInputFormat(*capture_format);
}
+ // TODO(thorcarpenter): When the adapter supports "only frame dropping"
+ // mode, also hook it up to screencast capturers.
+ video_capturer->SignalAdaptFrame.connect(
+ this, &WebRtcVideoChannelSendInfo::AdaptFrame);
}
}
+ void AdaptFrame(VideoCapturer* capturer, const VideoFrame* input,
+ VideoFrame** adapted) {
+ video_adapter_->AdaptFrame(input, adapted);
+ }
+
void ApplyCpuOptions(const VideoOptions& options) {
bool cpu_adapt, cpu_smoothing, adapt_third;
float low, med, high;
@@ -2004,17 +2008,15 @@
LOG(LS_INFO) << "Removing video stream " << ssrc
<< " with VideoEngine channel #"
<< channel_id;
+ bool ret = true;
if (engine()->vie()->base()->DeleteChannel(channel_id) == -1) {
LOG_RTCERR1(DeleteChannel, channel_id);
- // Leak the WebRtcVideoChannelRecvInfo owned by |it| but remove the channel
- // from recv_channels_.
- recv_channels_.erase(it);
- return false;
+ ret = false;
}
// Delete the WebRtcVideoChannelRecvInfo pointed to by it->second.
delete info;
recv_channels_.erase(it);
- return true;
+ return ret;
}
bool WebRtcVideoMediaChannel::StartSend() {
@@ -2117,18 +2119,6 @@
}
WebRtcVideoChannelSendInfo* WebRtcVideoMediaChannel::GetSendChannel(
- VideoCapturer* video_capturer) {
- for (SendChannelMap::iterator iter = send_channels_.begin();
- iter != send_channels_.end(); ++iter) {
- WebRtcVideoChannelSendInfo* send_channel = iter->second;
- if (send_channel->video_capturer() == video_capturer) {
- return send_channel;
- }
- }
- return NULL;
-}
-
-WebRtcVideoChannelSendInfo* WebRtcVideoMediaChannel::GetSendChannel(
uint32 local_ssrc) {
uint32 key;
if (!GetSendChannelKey(local_ssrc, &key)) {
@@ -2301,18 +2291,27 @@
sinfo.adapt_reason = send_channel->CurrentAdaptReason();
sinfo.capture_jitter_ms = -1;
sinfo.avg_encode_ms = -1;
+ sinfo.encode_usage_percent = -1;
+ sinfo.capture_queue_delay_ms_per_s = -1;
#ifdef USE_WEBRTC_DEV_BRANCH
int capture_jitter_ms = 0;
int avg_encode_time_ms = 0;
+ int encode_usage_percent = 0;
+ int capture_queue_delay_ms_per_s = 0;
if (engine()->vie()->base()->CpuOveruseMeasures(
- channel_id, &capture_jitter_ms, &avg_encode_time_ms) == 0) {
+ channel_id,
+ &capture_jitter_ms,
+ &avg_encode_time_ms,
+ &encode_usage_percent,
+ &capture_queue_delay_ms_per_s) == 0) {
sinfo.capture_jitter_ms = capture_jitter_ms;
sinfo.avg_encode_ms = avg_encode_time_ms;
+ sinfo.encode_usage_percent = encode_usage_percent;
+ sinfo.capture_queue_delay_ms_per_s = capture_queue_delay_ms_per_s;
}
#endif
-#ifdef USE_WEBRTC_DEV_BRANCH
// Get received RTCP statistics for the sender (reported by the remote
// client in a RTCP packet), if available.
// It's not a fatal error if we can't, since RTCP may not have arrived
@@ -2330,28 +2329,6 @@
outgoing_stream_rtcp_stats.fraction_lost) / (1 << 8);
sinfo.rtt_ms = outgoing_stream_rtt_ms;
}
-#else
- // Get received RTCP statistics for the sender, if available.
- // It's not a fatal error if we can't, since RTCP may not have arrived
- // yet.
- uint16 r_fraction_lost;
- unsigned int r_cumulative_lost;
- unsigned int r_extended_max;
- unsigned int r_jitter;
- int r_rtt_ms;
-
- if (engine_->vie()->rtp()->GetSentRTCPStatistics(
- channel_id,
- r_fraction_lost,
- r_cumulative_lost,
- r_extended_max,
- r_jitter, r_rtt_ms) == 0) {
- // Convert Q8 to float.
- sinfo.packets_lost = r_cumulative_lost;
- sinfo.fraction_lost = static_cast<float>(r_fraction_lost) / (1 << 8);
- sinfo.rtt_ms = r_rtt_ms;
- }
-#endif
info->senders.push_back(sinfo);
unsigned int channel_total_bitrate_sent = 0;
@@ -2406,7 +2383,6 @@
ssrc == 0)
continue;
-#ifdef USE_WEBRTC_DEV_BRANCH
webrtc::StreamDataCounters sent;
webrtc::StreamDataCounters received;
if (engine_->vie()->rtp()->GetRtpStatistics(channel->channel_id(),
@@ -2418,19 +2394,6 @@
rinfo.add_ssrc(ssrc);
rinfo.bytes_rcvd = received.bytes;
rinfo.packets_rcvd = received.packets;
-#else
- unsigned int bytes_sent, packets_sent, bytes_recv, packets_recv;
- if (engine_->vie()->rtp()->GetRTPStatistics(
- channel->channel_id(), bytes_sent, packets_sent, bytes_recv,
- packets_recv) != 0) {
- LOG_RTCERR1(GetRTPStatistics, channel->channel_id());
- return false;
- }
- VideoReceiverInfo rinfo;
- rinfo.add_ssrc(ssrc);
- rinfo.bytes_rcvd = bytes_recv;
- rinfo.packets_rcvd = packets_recv;
-#endif
rinfo.packets_lost = -1;
rinfo.packets_concealed = -1;
rinfo.fraction_lost = -1; // from SentRTCP
@@ -2442,7 +2405,6 @@
rinfo.framerate_output = fps;
channel->decoder_observer()->ExportTo(&rinfo);
-#ifdef USE_WEBRTC_DEV_BRANCH
// Get our locally created statistics of the received RTP stream.
webrtc::RtcpStatistics incoming_stream_rtcp_stats;
int incoming_stream_rtt_ms;
@@ -2455,21 +2417,6 @@
rinfo.fraction_lost = static_cast<float>(
incoming_stream_rtcp_stats.fraction_lost) / (1 << 8);
}
-#else
- // Get sent RTCP statistics.
- uint16 s_fraction_lost;
- unsigned int s_cumulative_lost;
- unsigned int s_extended_max;
- unsigned int s_jitter;
- int s_rtt_ms;
- if (engine_->vie()->rtp()->GetReceivedRTCPStatistics(channel->channel_id(),
- s_fraction_lost, s_cumulative_lost, s_extended_max,
- s_jitter, s_rtt_ms) == 0) {
- // Convert Q8 to float.
- rinfo.packets_lost = s_cumulative_lost;
- rinfo.fraction_lost = static_cast<float>(s_fraction_lost) / (1 << 8);
- }
-#endif
info->receivers.push_back(rinfo);
unsigned int estimated_recv_stream_bandwidth = 0;
@@ -2516,7 +2463,7 @@
send_channel->set_video_capturer(capturer);
capturer->SignalVideoFrame.connect(
this,
- &WebRtcVideoMediaChannel::AdaptAndSendFrame);
+ &WebRtcVideoMediaChannel::SendFrame);
if (!capturer->IsScreencast() && ratio_w_ != 0 && ratio_h_ != 0) {
capturer->UpdateAspectRatio(ratio_w_, ratio_h_);
}
@@ -2835,7 +2782,6 @@
}
}
if (suspend_below_min_bitrate_changed) {
-#ifdef USE_WEBRTC_DEV_BRANCH
if (options_.suspend_below_min_bitrate.GetWithDefaultIfUnset(false)) {
for (SendChannelMap::iterator it = send_channels_.begin();
it != send_channels_.end(); ++it) {
@@ -2845,7 +2791,6 @@
} else {
LOG(LS_WARNING) << "Cannot disable video suspension once it is enabled";
}
-#endif
}
return true;
}
@@ -2901,39 +2846,23 @@
return true;
}
-void WebRtcVideoMediaChannel::AdaptAndSendFrame(VideoCapturer* capturer,
- const VideoFrame* frame) {
- if (capturer->IsScreencast()) {
- // Do not adapt frames that are screencast.
- SendFrame(capturer, frame);
- return;
- }
- // TODO(thorcarpenter): This is broken. One capturer registered on two ssrc
- // will not send any video to the second ssrc send channel. We should remove
- // GetSendChannel(capturer) and pass in an ssrc here.
- WebRtcVideoChannelSendInfo* send_channel = GetSendChannel(capturer);
- if (!send_channel) {
- SendFrame(capturer, frame);
- return;
- }
- const VideoFrame* output_frame = NULL;
- send_channel->AdaptFrame(frame, &output_frame);
- if (output_frame) {
- SendFrame(send_channel, output_frame, capturer->IsScreencast());
- }
-}
-
-// TODO(zhurunz): Add unittests to test this function.
void WebRtcVideoMediaChannel::SendFrame(VideoCapturer* capturer,
const VideoFrame* frame) {
- // If there's send channel registers to the |capturer|, then only send the
- // frame to that channel and return. Otherwise send the frame to the default
- // channel, which currently taking frames from the engine.
- WebRtcVideoChannelSendInfo* send_channel = GetSendChannel(capturer);
- if (send_channel) {
- SendFrame(send_channel, frame, capturer->IsScreencast());
+ // If the |capturer| is registered to any send channel, then send the frame
+ // to those send channels.
+ bool capturer_is_channel_owned = false;
+ for (SendChannelMap::iterator iter = send_channels_.begin();
+ iter != send_channels_.end(); ++iter) {
+ WebRtcVideoChannelSendInfo* send_channel = iter->second;
+ if (send_channel->video_capturer() == capturer) {
+ SendFrame(send_channel, frame, capturer->IsScreencast());
+ capturer_is_channel_owned = true;
+ }
+ }
+ if (capturer_is_channel_owned) {
return;
}
+
// TODO(hellner): Remove below for loop once the captured frame no longer
// come from the engine, i.e. the engine no longer owns a capturer.
for (SendChannelMap::iterator iter = send_channels_.begin();
diff --git a/media/webrtc/webrtcvideoengine.h b/media/webrtc/webrtcvideoengine.h
index af4d627..d5f0e57 100644
--- a/media/webrtc/webrtcvideoengine.h
+++ b/media/webrtc/webrtcvideoengine.h
@@ -290,8 +290,6 @@
bool SendFrame(WebRtcVideoChannelSendInfo* channel_info,
const VideoFrame* frame, bool is_screencast);
- void AdaptAndSendFrame(VideoCapturer* capturer, const VideoFrame* frame);
-
// Thunk functions for use with HybridVideoEngine
void OnLocalFrame(VideoCapturer* capturer, const VideoFrame* frame) {
SendFrame(0u, frame, capturer->IsScreencast());
@@ -366,7 +364,6 @@
// If the local ssrc correspond to that of the default channel the key is 0.
// For all other channels the returned key will be the same as the local ssrc.
bool GetSendChannelKey(uint32 local_ssrc, uint32* key);
- WebRtcVideoChannelSendInfo* GetSendChannel(VideoCapturer* video_capturer);
WebRtcVideoChannelSendInfo* GetSendChannel(uint32 local_ssrc);
// Creates a new unique key that can be used for inserting a new send channel
// into |send_channels_|
diff --git a/media/webrtc/webrtcvideoengine_unittest.cc b/media/webrtc/webrtcvideoengine_unittest.cc
index e37bc3c..93ca9ad 100644
--- a/media/webrtc/webrtcvideoengine_unittest.cc
+++ b/media/webrtc/webrtcvideoengine_unittest.cc
@@ -69,6 +69,12 @@
static const unsigned int kNumberOfTemporalLayers = 1;
+static const uint32 kSsrcs1[] = {1};
+static const uint32 kSsrcs2[] = {1, 2};
+static const uint32 kSsrcs3[] = {1, 2, 3};
+static const uint32 kRtxSsrc1[] = {4};
+static const uint32 kRtxSsrcs3[] = {4, 5, 6};
+
class FakeViEWrapper : public cricket::ViEWrapper {
public:
@@ -117,11 +123,7 @@
return false;
}
cricket::WebRtcVideoFrame frame;
- size_t size = width * height * 3 / 2; // I420
- talk_base::scoped_ptr<uint8[]> pixel(new uint8[size]);
- if (!frame.Init(cricket::FOURCC_I420,
- width, height, width, height,
- pixel.get(), size, 1, 1, 0, 0, 0)) {
+ if (!frame.InitToBlack(width, height, 1, 1, 0, 0)) {
return false;
}
cricket::FakeVideoCapturer capturer;
@@ -137,11 +139,7 @@
return false;
}
cricket::WebRtcVideoFrame frame;
- size_t size = width * height * 3 / 2; // I420
- talk_base::scoped_ptr<uint8[]> pixel(new uint8[size]);
- if (!frame.Init(cricket::FOURCC_I420,
- width, height, width, height,
- pixel.get(), size, 1, 1, 0, timestamp, 0)) {
+ if (!frame.InitToBlack(width, height, 1, 1, 0, 0)) {
return false;
}
cricket::FakeVideoCapturer capturer;
@@ -1218,6 +1216,41 @@
EXPECT_FALSE(vie_.GetCaptureDenoising(capture_id));
}
+TEST_F(WebRtcVideoEngineTestFake, MultipleSendStreamsWithOneCapturer) {
+ EXPECT_TRUE(SetupEngine());
+ cricket::FakeVideoCapturer capturer;
+ for (unsigned int i = 0; i < sizeof(kSsrcs2)/sizeof(kSsrcs2[0]); ++i) {
+ EXPECT_TRUE(channel_->AddSendStream(
+ cricket::StreamParams::CreateLegacy(kSsrcs2[i])));
+ // Register the capturer to the ssrc.
+ EXPECT_TRUE(channel_->SetCapturer(kSsrcs2[i], &capturer));
+ }
+
+ const int channel0 = vie_.GetChannelFromLocalSsrc(kSsrcs2[0]);
+ ASSERT_NE(-1, channel0);
+ const int channel1 = vie_.GetChannelFromLocalSsrc(kSsrcs2[1]);
+ ASSERT_NE(-1, channel1);
+ ASSERT_NE(channel0, channel1);
+
+ std::vector<cricket::VideoCodec> codecs;
+ codecs.push_back(kVP8Codec);
+ EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+
+ cricket::WebRtcVideoFrame frame;
+ const size_t pixel_width = 1;
+ const size_t pixel_height = 1;
+ const int64 elapsed_time = 0;
+ const int64 time_stamp = 0;
+ EXPECT_TRUE(frame.InitToBlack(kVP8Codec.width, kVP8Codec.height,
+ pixel_width, pixel_height,
+ elapsed_time, time_stamp));
+ channel_->SendFrame(&capturer, &frame);
+
+ // Both channels should have received the frame.
+ EXPECT_EQ(1, vie_.GetIncomingFrameNum(channel0));
+ EXPECT_EQ(1, vie_.GetIncomingFrameNum(channel1));
+}
+
// Disabled since its flaky: b/11288120
TEST_F(WebRtcVideoEngineTestFake, DISABLED_SendReceiveBitratesStats) {
@@ -1764,8 +1797,14 @@
codecs.push_back(kVP8Codec);
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+ EXPECT_TRUE(channel_->AddSendStream(
+ cricket::StreamParams::CreateLegacy(kSsrc)));
+
EXPECT_TRUE(vie_.ExternalEncoderRegistered(channel_num, 100));
EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
+
+ // Remove stream previously added to free the external encoder instance.
+ EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
}
TEST_F(WebRtcVideoEngineTestFake, DontRegisterEncoderMultipleTimes) {
@@ -1778,6 +1817,9 @@
codecs.push_back(kVP8Codec);
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+ EXPECT_TRUE(channel_->AddSendStream(
+ cricket::StreamParams::CreateLegacy(kSsrc)));
+
EXPECT_TRUE(vie_.ExternalEncoderRegistered(channel_num, 100));
EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
EXPECT_EQ(1, encoder_factory_.GetNumCreatedEncoders());
@@ -1785,6 +1827,9 @@
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
EXPECT_EQ(1, encoder_factory_.GetNumCreatedEncoders());
+
+ // Remove stream previously added to free the external encoder instance.
+ EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
}
TEST_F(WebRtcVideoEngineTestFake, RegisterEncoderWithMultipleSendStreams) {
@@ -1916,9 +1961,15 @@
codecs.push_back(kVP8Codec);
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+ EXPECT_TRUE(channel_->AddSendStream(
+ cricket::StreamParams::CreateLegacy(kSsrc)));
+
EXPECT_TRUE(vie_.ExternalEncoderRegistered(channel_num, 100));
EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
EXPECT_EQ(1, encoder_factory_.GetNumCreatedEncoders());
+
+ // Remove stream previously added to free the external encoder instance.
+ EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
}
// Tests that OnReadyToSend will be propagated into ViE.
diff --git a/media/webrtc/webrtcvoiceengine.cc b/media/webrtc/webrtcvoiceengine.cc
index 1b77671..745a1e0 100644
--- a/media/webrtc/webrtcvoiceengine.cc
+++ b/media/webrtc/webrtcvoiceengine.cc
@@ -1609,11 +1609,7 @@
}
int WebRtcVoiceEngine::CreateVoiceChannel(VoEWrapper* voice_engine_wrapper) {
-#ifdef USE_WEBRTC_DEV_BRANCH
return voice_engine_wrapper->base()->CreateChannel(voe_config_);
-#else
- return voice_engine_wrapper->base()->CreateChannel();
-#endif
}
int WebRtcVoiceEngine::CreateMediaVoiceChannel() {
diff --git a/media/webrtc/webrtcvoiceengine_unittest.cc b/media/webrtc/webrtcvoiceengine_unittest.cc
index cf8a54f..4c3ba2a 100644
--- a/media/webrtc/webrtcvoiceengine_unittest.cc
+++ b/media/webrtc/webrtcvoiceengine_unittest.cc
@@ -2060,7 +2060,7 @@
char packets[4][sizeof(kPcmuFrame)];
for (size_t i = 0; i < ARRAY_SIZE(packets); ++i) {
memcpy(packets[i], kPcmuFrame, sizeof(kPcmuFrame));
- talk_base::SetBE32(packets[i] + 8, i);
+ talk_base::SetBE32(packets[i] + 8, static_cast<uint32>(i));
}
EXPECT_TRUE(voe_.CheckNoPacket(channel_num1));
EXPECT_TRUE(voe_.CheckNoPacket(channel_num2));
@@ -2192,7 +2192,8 @@
EXPECT_FALSE(channel_->PlayRingbackTone(0, true, true));
EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
// Check we can set and play a ringback tone.
- EXPECT_TRUE(channel_->SetRingbackTone(kRingbackTone, strlen(kRingbackTone)));
+ EXPECT_TRUE(channel_->SetRingbackTone(
+ kRingbackTone, static_cast<int>(strlen(kRingbackTone))));
EXPECT_TRUE(channel_->PlayRingbackTone(0, true, true));
EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num));
// Check we can stop the tone manually.
@@ -2217,7 +2218,8 @@
EXPECT_FALSE(channel_->PlayRingbackTone(2, true, true));
EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
// Check we can set and play a ringback tone on the correct ssrc.
- EXPECT_TRUE(channel_->SetRingbackTone(kRingbackTone, strlen(kRingbackTone)));
+ EXPECT_TRUE(channel_->SetRingbackTone(
+ kRingbackTone, static_cast<int>(strlen(kRingbackTone))));
EXPECT_FALSE(channel_->PlayRingbackTone(77, true, true));
EXPECT_TRUE(channel_->PlayRingbackTone(2, true, true));
EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num));
@@ -2836,7 +2838,7 @@
size_t size = 0;
EXPECT_TRUE(stream->GetSize(&size));
EXPECT_GT(size, 0U);
- const std::string logs(stream->GetBuffer());
+ const std::string logs(stream->GetBuffer(), size);
EXPECT_NE(std::string::npos, logs.find("ProcessThread"));
}
@@ -2910,9 +2912,9 @@
EXPECT_EQ(127, it->id);
} else if (it->name == "opus") {
EXPECT_EQ(111, it->id);
- ASSERT_NE(it->params.find("minptime"), it->params.end());
+ ASSERT_TRUE(it->params.find("minptime") != it->params.end());
EXPECT_EQ("10", it->params.find("minptime")->second);
- ASSERT_NE(it->params.find("maxptime"), it->params.end());
+ ASSERT_TRUE(it->params.find("maxptime") != it->params.end());
EXPECT_EQ("60", it->params.find("maxptime")->second);
}
}
@@ -2994,7 +2996,6 @@
ASSERT_GE(soundclip_channel, 0);
EXPECT_FALSE(voe_sc_.IsUsingExperimentalAcm(soundclip_channel));
-#ifdef USE_WEBRTC_DEV_BRANCH
// Set options to use experimental ACM.
cricket::AudioOptions options;
options.experimental_acm.Set(true);
@@ -3017,5 +3018,4 @@
soundclip_channel = engine_.CreateSoundclipVoiceChannel();
ASSERT_GE(soundclip_channel, 0);
EXPECT_FALSE(voe_sc_.IsUsingExperimentalAcm(soundclip_channel));
-#endif
}
diff --git a/session/media/channel.cc b/session/media/channel.cc
index e0aff89..8579db2 100644
--- a/session/media/channel.cc
+++ b/session/media/channel.cc
@@ -587,11 +587,16 @@
int BaseChannel::SetOption(SocketType type, talk_base::Socket::Option opt,
int value) {
+ TransportChannel* channel = NULL;
switch (type) {
- case ST_RTP: return transport_channel_->SetOption(opt, value);
- case ST_RTCP: return rtcp_transport_channel_->SetOption(opt, value);
- default: return -1;
+ case ST_RTP:
+ channel = transport_channel_;
+ break;
+ case ST_RTCP:
+ channel = rtcp_transport_channel_;
+ break;
}
+ return channel ? channel->SetOption(opt, value) : -1;
}
void BaseChannel::OnWritableState(TransportChannel* channel) {
@@ -2152,7 +2157,9 @@
// Tweak our video processing settings, if needed.
VideoOptions video_options;
media_channel()->GetOptions(&video_options);
- video_options.conference_mode.Set(video->conference_mode());
+ if (video->conference_mode()) {
+ video_options.conference_mode.Set(true);
+ }
video_options.buffered_mode_latency.Set(video->buffered_mode_latency());
if (!media_channel()->SetOptions(video_options)) {