#include "talk/media/webrtc/webrtcvie.h"
#include "talk/media/webrtc/webrtcvoe.h"
#include "talk/media/webrtc/webrtcvoiceengine.h"
+#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#if !defined(LIBPEERCONNECTION_LIB)
#ifndef HAVE_WEBRTC_VIDEO
external_capture_(external_capture),
capturer_updated_(false),
interval_(0),
- video_adapter_(new CoordinatedVideoAdapter),
cpu_monitor_(cpu_monitor) {
- overuse_observer_.reset(new WebRtcOveruseObserver(video_adapter_.get()));
- SignalCpuAdaptationUnable.repeat(video_adapter_->SignalCpuAdaptationUnable);
+ overuse_observer_.reset(new WebRtcOveruseObserver(&video_adapter_));
+ SignalCpuAdaptationUnable.repeat(video_adapter_.SignalCpuAdaptationUnable);
if (cpu_monitor) {
cpu_monitor->SignalUpdate.connect(
- video_adapter_.get(), &CoordinatedVideoAdapter::OnCpuLoadUpdated);
+ &video_adapter_, &CoordinatedVideoAdapter::OnCpuLoadUpdated);
}
}
bool sending() const { return sending_; }
void set_muted(bool on) {
// TODO(asapersson): add support.
- // video_adapter_->SetBlackOutput(on);
+ // video_adapter_.SetBlackOutput(on);
muted_ = on;
}
bool muted() {return muted_; }
if (video_format_ != cricket::VideoFormat()) {
interval_ = video_format_.interval;
}
- video_adapter_->OnOutputFormatRequest(video_format_);
+ video_adapter_.OnOutputFormatRequest(video_format_);
}
void set_interval(int64 interval) {
if (video_format() == cricket::VideoFormat()) {
VideoFormat format(codec.width, codec.height,
VideoFormat::FpsToInterval(codec.maxFramerate),
FOURCC_I420);
- if (video_adapter_->output_format().IsSize0x0()) {
- video_adapter_->SetOutputFormat(format);
+ if (video_adapter_.output_format().IsSize0x0()) {
+ video_adapter_.SetOutputFormat(format);
}
}
- 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();
+ return video_adapter_.adapt_reason();
}
webrtc::CpuOveruseObserver* overuse_observer() {
return overuse_observer_.get();
return;
}
capturer_updated_ = true;
+
+ // Disconnect from the previous video capturer.
+ if (video_capturer_) {
+ video_capturer_->SignalAdaptFrame.disconnect(this);
+ }
+
video_capturer_ = video_capturer;
if (video_capturer && !video_capturer->IsScreencast()) {
const VideoFormat* capture_format = video_capturer->GetCaptureFormat();
// be zero, and all frames may be dropped.
// Consider fixing this by having video_adapter keep a pointer to the
// video capturer.
- video_adapter_->SetInputFormat(*capture_format);
+ 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);
}
}
+ CoordinatedVideoAdapter* video_adapter() { return &video_adapter_; }
+
+ 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;
if (options.adapt_input_to_cpu_usage.Get(&cpu_adapt)) {
- video_adapter_->set_cpu_adaptation(cpu_adapt);
+ video_adapter_.set_cpu_adaptation(cpu_adapt);
}
if (options.adapt_cpu_with_smoothing.Get(&cpu_smoothing)) {
- video_adapter_->set_cpu_smoothing(cpu_smoothing);
+ video_adapter_.set_cpu_smoothing(cpu_smoothing);
}
if (options.process_adaptation_threshhold.Get(&med)) {
- video_adapter_->set_process_threshold(med);
+ video_adapter_.set_process_threshold(med);
}
if (options.system_low_adaptation_threshhold.Get(&low)) {
- video_adapter_->set_low_system_threshold(low);
+ video_adapter_.set_low_system_threshold(low);
}
if (options.system_high_adaptation_threshhold.Get(&high)) {
- video_adapter_->set_high_system_threshold(high);
+ video_adapter_.set_high_system_threshold(high);
}
if (options.video_adapt_third.Get(&adapt_third)) {
- video_adapter_->set_scale_third(adapt_third);
+ video_adapter_.set_scale_third(adapt_third);
}
}
void SetCpuOveruseDetection(bool enable) {
if (cpu_monitor_ && enable) {
- cpu_monitor_->SignalUpdate.disconnect(video_adapter_.get());
+ cpu_monitor_->SignalUpdate.disconnect(&video_adapter_);
}
overuse_observer_->Enable(enable);
- video_adapter_->set_cpu_adaptation(enable);
+ video_adapter_.set_cpu_adaptation(enable);
}
void ProcessFrame(const VideoFrame& original_frame, bool mute,
int64 interval_;
- talk_base::scoped_ptr<CoordinatedVideoAdapter> video_adapter_;
+ CoordinatedVideoAdapter video_adapter_;
talk_base::CpuMonitor* cpu_monitor_;
talk_base::scoped_ptr<WebRtcOveruseObserver> overuse_observer_;
};
return true;
}
-bool WebRtcVideoMediaChannel::GetStats(VideoMediaInfo* info) {
+bool WebRtcVideoMediaChannel::GetStats(const StatsOptions& options,
+ VideoMediaInfo* info) {
// Get sender statistics and build VideoSenderInfo.
unsigned int total_bitrate_sent = 0;
unsigned int video_bitrate_sent = 0;
sinfo.firs_rcvd = -1;
sinfo.nacks_rcvd = -1;
sinfo.rtt_ms = -1;
- sinfo.frame_width = static_cast<int>(channel_stream_info->width());
- sinfo.frame_height = static_cast<int>(channel_stream_info->height());
+ sinfo.input_frame_width = static_cast<int>(channel_stream_info->width());
+ sinfo.input_frame_height =
+ static_cast<int>(channel_stream_info->height());
+ webrtc::VideoCodec vie_codec;
+ if (engine()->vie()->codec()->GetSendCodec(channel_id, vie_codec) == 0) {
+ sinfo.send_frame_width = vie_codec.width;
+ sinfo.send_frame_height = vie_codec.height;
+ } else {
+ sinfo.send_frame_width = -1;
+ sinfo.send_frame_height = -1;
+ LOG_RTCERR1(GetSendCodec, channel_id);
+ }
sinfo.framerate_input = channel_stream_info->framerate();
sinfo.framerate_sent = send_channel->encoder_observer()->framerate();
sinfo.nominal_bitrate = send_channel->encoder_observer()->bitrate();
LOG_RTCERR1(GetEstimatedReceiveBandwidth, channel->channel_id());
}
}
-
// Build BandwidthEstimationInfo.
// TODO(zhurunz): Add real unittest for this.
BandwidthEstimationInfo bwe;
+ // TODO(jiayl): remove the condition when the necessary changes are available
+ // outside the dev branch.
+#ifdef USE_WEBRTC_DEV_BRANCH
+ if (options.include_received_propagation_stats) {
+ webrtc::ReceiveBandwidthEstimatorStats additional_stats;
+ // Only call for the default channel because the returned stats are
+ // collected for all the channels using the same estimator.
+ if (engine_->vie()->rtp()->GetReceiveBandwidthEstimatorStats(
+ recv_channels_[0]->channel_id(), &additional_stats) == 0) {
+ bwe.total_received_propagation_delta_ms =
+ additional_stats.total_propagation_time_delta_ms;
+ bwe.recent_received_propagation_delta_ms.swap(
+ additional_stats.recent_propagation_time_delta_ms);
+ bwe.recent_received_packet_group_arrival_time_ms.swap(
+ additional_stats.recent_arrival_time_ms);
+ }
+ }
+#endif
+
// Calculations done above per send/receive stream.
bwe.actual_enc_bitrate = video_bitrate_sent;
bwe.transmit_bitrate = total_bitrate_sent;
return false;
}
}
+
+ if (send_time_extension) {
+ // For video RTP packets, we would like to update AbsoluteSendTimeHeader
+ // Extension closer to the network, @ socket level before sending.
+ // Pushing the extension id to socket layer.
+ MediaChannel::SetOption(NetworkInterface::ST_RTP,
+ talk_base::Socket::OPT_RTP_SENDTIME_EXTN_ID,
+ send_time_extension->id);
+ }
return true;
}
+int WebRtcVideoMediaChannel::GetRtpSendTimeExtnId() const {
+ const RtpHeaderExtension* send_time_extension = FindHeaderExtension(
+ send_extensions_, kRtpAbsoluteSendTimeHeaderExtension);
+ if (send_time_extension) {
+ return send_time_extension->id;
+ }
+ return -1;
+}
+
bool WebRtcVideoMediaChannel::SetStartSendBandwidth(int bps) {
LOG(LS_INFO) << "WebRtcVideoMediaChannel::SetStartSendBandwidth";
return true;
}
-// TODO(zhurunz): Add unittests to test this function.
+bool WebRtcVideoMediaChannel::GetVideoAdapter(
+ uint32 ssrc, CoordinatedVideoAdapter** video_adapter) {
+ SendChannelMap::iterator it = send_channels_.find(ssrc);
+ if (it == send_channels_.end()) {
+ return false;
+ }
+ *video_adapter = it->second->video_adapter();
+ return true;
+}
+
void WebRtcVideoMediaChannel::SendFrame(VideoCapturer* capturer,
const VideoFrame* frame) {
// If the |capturer| is registered to any send channel, then send the frame
}
}
+ // Start receiving for both receive and send channels so that we get incoming
+ // RTP (if receiving) as well as RTCP feedback (if sending).
+ if (engine()->vie()->base()->StartReceive(channel_id) != 0) {
+ LOG_RTCERR1(StartReceive, channel_id);
+ return false;
+ }
+
return true;
}
}
}
}
-
- // Start receiving packets if at least one receive codec has been set.
- if (!receive_codecs_.empty()) {
- if (engine()->vie()->base()->StartReceive(channel_id) != 0) {
- LOG_RTCERR1(StartReceive, channel_id);
- return false;
- }
- }
return true;
}