Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(471)

Unified Diff: remoting/host/video_frame_pump.cc

Issue 1365663003: Add UMA histograms for more detailed latency tracking on the CRD host. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixed tests Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/host/video_frame_pump.h ('k') | remoting/proto/video.proto » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/host/video_frame_pump.cc
diff --git a/remoting/host/video_frame_pump.cc b/remoting/host/video_frame_pump.cc
index 37d9da7c25e1ff47bc6b8bda8bf9488eac436be7..58b72db1ab03bdaaf38dabb44c35217ef6f06027 100644
--- a/remoting/host/video_frame_pump.cc
+++ b/remoting/host/video_frame_pump.cc
@@ -20,28 +20,6 @@
namespace remoting {
-namespace {
-
-scoped_ptr<VideoPacket> EncodeFrame(VideoEncoder* encoder,
- scoped_ptr<webrtc::DesktopFrame> frame) {
- scoped_ptr<VideoPacket> packet;
-
- // If |frame| is non-NULL then let the encoder process it.
- if (frame) {
- packet = encoder->Encode(*frame);
- }
-
- // If |frame| is NULL, or the encoder returned nothing, return an empty
- // packet.
- if (!packet) {
- packet.reset(new VideoPacket());
- }
-
- return packet.Pass();
-}
-
-} // namespace
-
// Interval between empty keep-alive frames. These frames are sent only when the
// stream is paused or inactive for some other reason (e.g. when blocked on
// capturer). To prevent PseudoTCP from resetting congestion window this value
@@ -50,6 +28,16 @@ static const int kKeepAlivePacketIntervalMs = 200;
static bool g_enable_timestamps = false;
+VideoFramePump::FrameTimestamps::FrameTimestamps() {}
+VideoFramePump::FrameTimestamps::~FrameTimestamps() {}
+
+VideoFramePump::PacketWithTimestamps::PacketWithTimestamps(
+ scoped_ptr<VideoPacket> packet,
+ scoped_ptr<FrameTimestamps> timestamps)
+ : packet(packet.Pass()), timestamps(timestamps.Pass()) {}
+
+VideoFramePump::PacketWithTimestamps::~PacketWithTimestamps() {}
+
// static
void VideoFramePump::EnableTimestampsForTests() {
g_enable_timestamps = true;
@@ -72,7 +60,6 @@ VideoFramePump::VideoFramePump(
false),
capture_scheduler_(base::Bind(&VideoFramePump::CaptureNextFrame,
base::Unretained(this))),
- latest_event_timestamp_(0),
weak_factory_(this) {
DCHECK(encoder_);
DCHECK(video_stub_);
@@ -91,10 +78,13 @@ void VideoFramePump::Pause(bool pause) {
capture_scheduler_.Pause(pause);
}
-void VideoFramePump::SetLatestEventTimestamp(int64 latest_event_timestamp) {
+void VideoFramePump::OnInputEventReceived(int64_t event_timestamp) {
DCHECK(thread_checker_.CalledOnValidThread());
- latest_event_timestamp_ = latest_event_timestamp;
+ if (!next_frame_timestamps_)
+ next_frame_timestamps_.reset(new FrameTimestamps());
+ next_frame_timestamps_->input_event_client_timestamp = event_timestamp;
+ next_frame_timestamps_->input_event_received_time = base::TimeTicks::Now();
}
void VideoFramePump::SetLosslessEncode(bool want_lossless) {
@@ -123,45 +113,126 @@ void VideoFramePump::OnCaptureCompleted(webrtc::DesktopFrame* frame) {
capture_scheduler_.OnCaptureCompleted();
+ captured_frame_timestamps_->capture_ended_time = base::TimeTicks::Now();
+
// Even when |frame| is nullptr we still need to post it to the encode thread
// to make sure frames are freed in the same order they are received and
// that we don't start capturing frame n+2 before frame n is freed.
base::PostTaskAndReplyWithResult(
encode_task_runner_.get(), FROM_HERE,
- base::Bind(&EncodeFrame, encoder_.get(),
- base::Passed(make_scoped_ptr(frame))),
- base::Bind(&VideoFramePump::SendEncodedFrame, weak_factory_.GetWeakPtr(),
- latest_event_timestamp_, base::TimeTicks::Now()));
+ base::Bind(&VideoFramePump::EncodeFrame, encoder_.get(),
+ base::Passed(make_scoped_ptr(frame)),
+ base::Passed(&captured_frame_timestamps_)),
+ base::Bind(&VideoFramePump::OnFrameEncoded, weak_factory_.GetWeakPtr()));
}
void VideoFramePump::CaptureNextFrame() {
DCHECK(thread_checker_.CalledOnValidThread());
+ // |next_frame_timestamps_| is not set if no input events were received since
+ // the previous frame. In that case create FrameTimestamps instance without
+ // setting |input_event_client_timestamp| and |input_event_received_time|.
+ if (!next_frame_timestamps_)
+ next_frame_timestamps_.reset(new FrameTimestamps());
+
+ captured_frame_timestamps_ = next_frame_timestamps_.Pass();
+ captured_frame_timestamps_->capture_started_time = base::TimeTicks::Now();
+
capturer_->Capture(webrtc::DesktopRegion());
}
-void VideoFramePump::SendEncodedFrame(int64 latest_event_timestamp,
- base::TimeTicks timestamp,
- scoped_ptr<VideoPacket> packet) {
+// static
+scoped_ptr<VideoFramePump::PacketWithTimestamps> VideoFramePump::EncodeFrame(
+ VideoEncoder* encoder,
+ scoped_ptr<webrtc::DesktopFrame> frame,
+ scoped_ptr<FrameTimestamps> timestamps) {
+ timestamps->encode_started_time = base::TimeTicks::Now();
+
+ scoped_ptr<VideoPacket> packet;
+ // If |frame| is non-NULL then let the encoder process it.
+ if (frame)
+ packet = encoder->Encode(*frame);
+
+ // If |frame| is NULL, or the encoder returned nothing, return an empty
+ // packet.
+ if (!packet)
+ packet.reset(new VideoPacket());
+
+ if (frame)
+ packet->set_capture_time_ms(frame->capture_time_ms());
+
+ timestamps->encode_ended_time = base::TimeTicks::Now();
+
+ return make_scoped_ptr(
+ new PacketWithTimestamps(packet.Pass(), timestamps.Pass()));
+}
+
+void VideoFramePump::OnFrameEncoded(scoped_ptr<PacketWithTimestamps> packet) {
DCHECK(thread_checker_.CalledOnValidThread());
- if (g_enable_timestamps)
- packet->set_timestamp(timestamp.ToInternalValue());
+ capture_scheduler_.OnFrameEncoded(packet->packet.get());
- packet->set_latest_event_timestamp(latest_event_timestamp);
+ if (send_pending_) {
+ pending_packets_.push_back(packet.Pass());
+ } else {
+ SendPacket(packet.Pass());
+ }
+}
- capture_scheduler_.OnFrameEncoded(packet.get());
+void VideoFramePump::SendPacket(scoped_ptr<PacketWithTimestamps> packet) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!send_pending_);
- video_stub_->ProcessVideoPacket(packet.Pass(),
+ packet->timestamps->can_send_time = base::TimeTicks::Now();
+ UpdateFrameTimers(packet->packet.get(), packet->timestamps.get());
+
+ send_pending_ = true;
+ video_stub_->ProcessVideoPacket(packet->packet.Pass(),
base::Bind(&VideoFramePump::OnVideoPacketSent,
weak_factory_.GetWeakPtr()));
}
+void VideoFramePump::UpdateFrameTimers(VideoPacket* packet,
+ FrameTimestamps* timestamps) {
+ if (g_enable_timestamps)
+ packet->set_timestamp(timestamps->capture_ended_time.ToInternalValue());
+
+
+ if (!timestamps->input_event_received_time.is_null()) {
+ packet->set_capture_pending_time_ms((timestamps->capture_started_time -
+ timestamps->input_event_received_time)
+ .InMilliseconds());
+ packet->set_latest_event_timestamp(
+ timestamps->input_event_client_timestamp);
+ }
+
+ packet->set_capture_overhead_time_ms(
+ (timestamps->capture_ended_time - timestamps->capture_started_time)
+ .InMilliseconds() -
+ packet->capture_time_ms());
+
+ packet->set_encode_pending_time_ms(
+ (timestamps->encode_started_time - timestamps->capture_ended_time)
+ .InMilliseconds());
+
+ packet->set_send_pending_time_ms(
+ (timestamps->can_send_time - timestamps->encode_ended_time)
+ .InMilliseconds());
+}
+
void VideoFramePump::OnVideoPacketSent() {
DCHECK(thread_checker_.CalledOnValidThread());
+ send_pending_ = false;
capture_scheduler_.OnFrameSent();
keep_alive_timer_.Reset();
+
+ // Send next packet if any.
+ if (!pending_packets_.empty()) {
+ scoped_ptr<PacketWithTimestamps> next(pending_packets_.front());
+ pending_packets_.weak_erase(pending_packets_.begin());
+ SendPacket(next.Pass());
+ }
}
void VideoFramePump::SendKeepAlivePacket() {
« no previous file with comments | « remoting/host/video_frame_pump.h ('k') | remoting/proto/video.proto » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698