sergeyu | 0fc40f9 | 2015-12-10 18:42:43 | [diff] [blame] | 1 | // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "remoting/protocol/webrtc_video_stream.h" |
| 6 | |
yuweih | 1481d8d | 2017-04-04 01:43:51 | [diff] [blame] | 7 | #include <utility> |
| 8 | |
Zijie He | 3d3751dc | 2017-10-26 19:29:54 | [diff] [blame] | 9 | #include "base/bind.h" |
sergeyu | 0fc40f9 | 2015-12-10 18:42:43 | [diff] [blame] | 10 | #include "base/logging.h" |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 11 | #include "base/memory/ptr_util.h" |
Zijie He | caea1e4 | 2017-10-11 23:20:35 | [diff] [blame] | 12 | #include "build/build_config.h" |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 13 | #include "remoting/base/constants.h" |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 14 | #include "remoting/codec/webrtc_video_encoder_proxy.h" |
sergeyu | 2becb601 | 2016-09-13 18:41:32 | [diff] [blame] | 15 | #include "remoting/codec/webrtc_video_encoder_vpx.h" |
sergeyu | 0936463 | 2016-08-11 00:08:10 | [diff] [blame] | 16 | #include "remoting/protocol/frame_stats.h" |
| 17 | #include "remoting/protocol/host_video_stats_dispatcher.h" |
isheriff | 87c2fbd | 2016-04-13 21:21:44 | [diff] [blame] | 18 | #include "remoting/protocol/webrtc_dummy_video_capturer.h" |
sergeyu | 0eaa513 | 2016-09-20 01:39:34 | [diff] [blame] | 19 | #include "remoting/protocol/webrtc_frame_scheduler_simple.h" |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 20 | #include "remoting/protocol/webrtc_transport.h" |
kjellander | 9770545 | 2016-02-10 14:51:24 | [diff] [blame] | 21 | #include "third_party/webrtc/api/mediastreaminterface.h" |
| 22 | #include "third_party/webrtc/api/peerconnectioninterface.h" |
| 23 | #include "third_party/webrtc/api/test/fakeconstraints.h" |
isheriff | 87c2fbd | 2016-04-13 21:21:44 | [diff] [blame] | 24 | #include "third_party/webrtc/media/base/videocapturer.h" |
sergeyu | 0fc40f9 | 2015-12-10 18:42:43 | [diff] [blame] | 25 | |
Zijie He | caea1e4 | 2017-10-11 23:20:35 | [diff] [blame] | 26 | #if defined(USE_H264_ENCODER) |
| 27 | #include "remoting/codec/webrtc_video_encoder_gpu.h" |
| 28 | #endif |
| 29 | |
sergeyu | 0fc40f9 | 2015-12-10 18:42:43 | [diff] [blame] | 30 | namespace remoting { |
| 31 | namespace protocol { |
| 32 | |
Zijie He | cc8a077 | 2017-10-17 03:19:32 | [diff] [blame] | 33 | namespace { |
| 34 | |
sergeyu | bf81cd6 | 2016-01-10 08:00:42 | [diff] [blame] | 35 | const char kStreamLabel[] = "screen_stream"; |
| 36 | const char kVideoLabel[] = "screen_video"; |
| 37 | |
Zijie He | cc8a077 | 2017-10-17 03:19:32 | [diff] [blame] | 38 | std::string EncodeResultToString(WebrtcVideoEncoder::EncodeResult result) { |
| 39 | using EncodeResult = WebrtcVideoEncoder::EncodeResult; |
| 40 | |
| 41 | switch (result) { |
| 42 | case EncodeResult::SUCCEEDED: |
| 43 | return "Succeeded"; |
| 44 | case EncodeResult::FRAME_SIZE_EXCEEDS_CAPABILITY: |
| 45 | return "Frame size exceeds capability"; |
| 46 | case EncodeResult::UNKNOWN_ERROR: |
| 47 | return "Unknown error"; |
| 48 | } |
| 49 | NOTREACHED(); |
| 50 | return ""; |
| 51 | } |
| 52 | |
| 53 | } // namespace |
| 54 | |
zijiehe | 805f2ca | 2017-03-27 00:56:00 | [diff] [blame] | 55 | struct WebrtcVideoStream::FrameStats { |
sergeyu | e84cc62 | 2016-10-15 06:54:03 | [diff] [blame] | 56 | // The following fields is not null only for one frame after each incoming |
| 57 | // input event. |
| 58 | InputEventTimestamps input_event_timestamps; |
sergeyu | 0936463 | 2016-08-11 00:08:10 | [diff] [blame] | 59 | |
| 60 | base::TimeTicks capture_started_time; |
| 61 | base::TimeTicks capture_ended_time; |
| 62 | base::TimeDelta capture_delay; |
| 63 | base::TimeTicks encode_started_time; |
| 64 | base::TimeTicks encode_ended_time; |
zijiehe | 805f2ca | 2017-03-27 00:56:00 | [diff] [blame] | 65 | |
| 66 | uint32_t capturer_id = 0; |
sergeyu | 0936463 | 2016-08-11 00:08:10 | [diff] [blame] | 67 | }; |
| 68 | |
Zijie He | ba57151 | 2017-11-20 20:22:23 | [diff] [blame] | 69 | WebrtcVideoStream::WebrtcVideoStream(const SessionOptions& session_options) |
| 70 | : video_stats_dispatcher_(kStreamLabel), |
| 71 | session_options_(session_options), |
| 72 | weak_factory_(this) { |
Zijie He | 3d3751dc | 2017-10-26 19:29:54 | [diff] [blame] | 73 | encoder_selector_.RegisterEncoder( |
| 74 | base::Bind(&WebrtcVideoEncoderVpx::IsSupportedByVP8), |
| 75 | base::Bind(&WebrtcVideoEncoderVpx::CreateForVP8)); |
| 76 | encoder_selector_.RegisterEncoder( |
| 77 | base::Bind(&WebrtcVideoEncoderVpx::IsSupportedByVP9), |
| 78 | base::Bind(&WebrtcVideoEncoderVpx::CreateForVP9)); |
| 79 | #if defined(USE_H264_ENCODER) |
| 80 | encoder_selector_.RegisterEncoder( |
| 81 | base::Bind(&WebrtcVideoEncoderGpu::IsSupportedByH264), |
| 82 | base::Bind(&WebrtcVideoEncoderGpu::CreateForH264)); |
| 83 | #endif |
| 84 | } |
sergeyu | 0fc40f9 | 2015-12-10 18:42:43 | [diff] [blame] | 85 | |
| 86 | WebrtcVideoStream::~WebrtcVideoStream() { |
joedow | 18837eb | 2017-05-17 18:28:24 | [diff] [blame] | 87 | DCHECK(thread_checker_.CalledOnValidThread()); |
sergeyu | bf81cd6 | 2016-01-10 08:00:42 | [diff] [blame] | 88 | if (stream_) { |
| 89 | for (const auto& track : stream_->GetVideoTracks()) { |
sergeyu | bf81cd6 | 2016-01-10 08:00:42 | [diff] [blame] | 90 | stream_->RemoveTrack(track.get()); |
| 91 | } |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 92 | peer_connection_->RemoveStream(stream_.get()); |
sergeyu | 0fc40f9 | 2015-12-10 18:42:43 | [diff] [blame] | 93 | } |
sergeyu | bf81cd6 | 2016-01-10 08:00:42 | [diff] [blame] | 94 | } |
| 95 | |
sergeyu | 24b257a1 | 2016-10-09 02:46:28 | [diff] [blame] | 96 | void WebrtcVideoStream::Start( |
dcheng | 0765c49 | 2016-04-06 22:41:53 | [diff] [blame] | 97 | std::unique_ptr<webrtc::DesktopCapturer> desktop_capturer, |
isheriff | 87c2fbd | 2016-04-13 21:21:44 | [diff] [blame] | 98 | WebrtcTransport* webrtc_transport, |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 99 | scoped_refptr<base::SequencedTaskRunner> encode_task_runner) { |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 100 | DCHECK(thread_checker_.CalledOnValidThread()); |
isheriff | 87c2fbd | 2016-04-13 21:21:44 | [diff] [blame] | 101 | DCHECK(webrtc_transport); |
| 102 | DCHECK(desktop_capturer); |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 103 | DCHECK(encode_task_runner); |
sergeyu | bf81cd6 | 2016-01-10 08:00:42 | [diff] [blame] | 104 | |
isheriff | 87c2fbd | 2016-04-13 21:21:44 | [diff] [blame] | 105 | scoped_refptr<webrtc::PeerConnectionFactoryInterface> peer_connection_factory( |
| 106 | webrtc_transport->peer_connection_factory()); |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 107 | peer_connection_ = webrtc_transport->peer_connection(); |
isheriff | 87c2fbd | 2016-04-13 21:21:44 | [diff] [blame] | 108 | DCHECK(peer_connection_factory); |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 109 | DCHECK(peer_connection_); |
isheriff | 87c2fbd | 2016-04-13 21:21:44 | [diff] [blame] | 110 | |
gab | 10ae436 | 2016-11-02 23:34:53 | [diff] [blame] | 111 | encode_task_runner_ = std::move(encode_task_runner); |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 112 | capturer_ = std::move(desktop_capturer); |
| 113 | webrtc_transport_ = webrtc_transport; |
yuweih | 1481d8d | 2017-04-04 01:43:51 | [diff] [blame] | 114 | |
| 115 | webrtc_transport_->video_encoder_factory()->RegisterEncoderSelectedCallback( |
| 116 | base::Bind(&WebrtcVideoStream::OnEncoderCreated, |
| 117 | weak_factory_.GetWeakPtr())); |
| 118 | |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 119 | capturer_->Start(this); |
sergeyu | bf81cd6 | 2016-01-10 08:00:42 | [diff] [blame] | 120 | |
| 121 | // Set video stream constraints. |
| 122 | webrtc::FakeConstraints video_constraints; |
| 123 | video_constraints.AddMandatory( |
| 124 | webrtc::MediaConstraintsInterface::kMinFrameRate, 5); |
| 125 | |
isheriff | 87c2fbd | 2016-04-13 21:21:44 | [diff] [blame] | 126 | rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> src = |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 127 | peer_connection_factory->CreateVideoSource(new WebrtcDummyVideoCapturer(), |
| 128 | &video_constraints); |
sergeyu | bf81cd6 | 2016-01-10 08:00:42 | [diff] [blame] | 129 | rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track = |
isheriff | 87c2fbd | 2016-04-13 21:21:44 | [diff] [blame] | 130 | peer_connection_factory->CreateVideoTrack(kVideoLabel, src); |
sergeyu | bf81cd6 | 2016-01-10 08:00:42 | [diff] [blame] | 131 | |
| 132 | stream_ = peer_connection_factory->CreateLocalMediaStream(kStreamLabel); |
| 133 | |
sergeyu | 24b257a1 | 2016-10-09 02:46:28 | [diff] [blame] | 134 | // AddTrack() may fail only if there is another track with the same name, |
| 135 | // which is impossible because it's a brand new stream. |
| 136 | bool result = stream_->AddTrack(video_track.get()); |
| 137 | DCHECK(result); |
| 138 | |
| 139 | // AddStream() may fail if there is another stream with the same name or when |
| 140 | // the PeerConnection is closed, neither is expected. |
| 141 | result = peer_connection_->AddStream(stream_.get()); |
| 142 | DCHECK(result); |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 143 | |
Zijie He | ba57151 | 2017-11-20 20:22:23 | [diff] [blame] | 144 | scheduler_.reset(new WebrtcFrameSchedulerSimple(session_options_)); |
sergeyu | 78f725b | 2016-10-11 23:34:48 | [diff] [blame] | 145 | scheduler_->Start( |
| 146 | webrtc_transport_->video_encoder_factory(), |
| 147 | base::Bind(&WebrtcVideoStream::CaptureNextFrame, base::Unretained(this))); |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 148 | |
sergeyu | 0936463 | 2016-08-11 00:08:10 | [diff] [blame] | 149 | video_stats_dispatcher_.Init(webrtc_transport_->CreateOutgoingChannel( |
| 150 | video_stats_dispatcher_.channel_name()), |
| 151 | this); |
sergeyu | 0fc40f9 | 2015-12-10 18:42:43 | [diff] [blame] | 152 | } |
| 153 | |
sergeyu | e84cc62 | 2016-10-15 06:54:03 | [diff] [blame] | 154 | void WebrtcVideoStream::SetEventTimestampsSource( |
| 155 | scoped_refptr<InputEventTimestampsSource> event_timestamps_source) { |
| 156 | event_timestamps_source_ = event_timestamps_source; |
| 157 | } |
| 158 | |
sergeyu | 0fc40f9 | 2015-12-10 18:42:43 | [diff] [blame] | 159 | void WebrtcVideoStream::Pause(bool pause) { |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 160 | DCHECK(thread_checker_.CalledOnValidThread()); |
sergeyu | 0eaa513 | 2016-09-20 01:39:34 | [diff] [blame] | 161 | scheduler_->Pause(pause); |
sergeyu | 0fc40f9 | 2015-12-10 18:42:43 | [diff] [blame] | 162 | } |
| 163 | |
sergeyu | 0fc40f9 | 2015-12-10 18:42:43 | [diff] [blame] | 164 | void WebrtcVideoStream::SetLosslessEncode(bool want_lossless) { |
| 165 | NOTIMPLEMENTED(); |
| 166 | } |
| 167 | |
| 168 | void WebrtcVideoStream::SetLosslessColor(bool want_lossless) { |
| 169 | NOTIMPLEMENTED(); |
| 170 | } |
| 171 | |
sergeyu | ad51be8 | 2016-06-22 06:04:39 | [diff] [blame] | 172 | void WebrtcVideoStream::SetObserver(Observer* observer) { |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 173 | DCHECK(thread_checker_.CalledOnValidThread()); |
sergeyu | ad51be8 | 2016-06-22 06:04:39 | [diff] [blame] | 174 | observer_ = observer; |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 175 | } |
| 176 | |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 177 | void WebrtcVideoStream::OnCaptureResult( |
| 178 | webrtc::DesktopCapturer::Result result, |
| 179 | std::unique_ptr<webrtc::DesktopFrame> frame) { |
| 180 | DCHECK(thread_checker_.CalledOnValidThread()); |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 181 | |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 182 | current_frame_stats_->capture_ended_time = base::TimeTicks::Now(); |
| 183 | current_frame_stats_->capture_delay = |
sergeyu | 14b918b | 2017-01-09 23:10:24 | [diff] [blame] | 184 | base::TimeDelta::FromMilliseconds(frame ? frame->capture_time_ms() : 0); |
sergeyu | 0936463 | 2016-08-11 00:08:10 | [diff] [blame] | 185 | |
sergeyu | 2becb601 | 2016-09-13 18:41:32 | [diff] [blame] | 186 | WebrtcVideoEncoder::FrameParams frame_params; |
sergeyu | 14b918b | 2017-01-09 23:10:24 | [diff] [blame] | 187 | if (!scheduler_->OnFrameCaptured(frame.get(), &frame_params)) { |
sergeyu | 0eaa513 | 2016-09-20 01:39:34 | [diff] [blame] | 188 | return; |
sergeyu | 14b918b | 2017-01-09 23:10:24 | [diff] [blame] | 189 | } |
| 190 | |
| 191 | // TODO(sergeyu): Handle ERROR_PERMANENT result here. |
| 192 | if (frame) { |
| 193 | webrtc::DesktopVector dpi = |
| 194 | frame->dpi().is_zero() ? webrtc::DesktopVector(kDefaultDpi, kDefaultDpi) |
| 195 | : frame->dpi(); |
| 196 | |
| 197 | if (!frame_size_.equals(frame->size()) || !frame_dpi_.equals(dpi)) { |
| 198 | frame_size_ = frame->size(); |
| 199 | frame_dpi_ = dpi; |
| 200 | if (observer_) |
| 201 | observer_->OnVideoSizeChanged(this, frame_size_, frame_dpi_); |
| 202 | } |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 203 | |
| 204 | current_frame_stats_->capturer_id = frame->capturer_id(); |
Zijie He | 3d3751dc | 2017-10-26 19:29:54 | [diff] [blame] | 205 | |
| 206 | if (!encoder_) { |
| 207 | encoder_selector_.SetDesktopFrame(*frame); |
| 208 | encoder_ = encoder_selector_.CreateEncoder(); |
| 209 | |
| 210 | // TODO(zijiehe): Permanently stop the video stream if we cannot create an |
| 211 | // encoder for the |frame|. |
| 212 | } |
sergeyu | 14b918b | 2017-01-09 23:10:24 | [diff] [blame] | 213 | } |
sergeyu | 2becb601 | 2016-09-13 18:41:32 | [diff] [blame] | 214 | |
Zijie He | 3d3751dc | 2017-10-26 19:29:54 | [diff] [blame] | 215 | if (encoder_) { |
| 216 | current_frame_stats_->encode_started_time = base::TimeTicks::Now(); |
| 217 | encoder_->Encode( |
| 218 | std::move(frame), frame_params, |
| 219 | base::Bind(&WebrtcVideoStream::OnFrameEncoded, base::Unretained(this))); |
| 220 | } |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 221 | } |
| 222 | |
sergeyu | 0936463 | 2016-08-11 00:08:10 | [diff] [blame] | 223 | void WebrtcVideoStream::OnChannelInitialized( |
| 224 | ChannelDispatcherBase* channel_dispatcher) { |
| 225 | DCHECK(&video_stats_dispatcher_ == channel_dispatcher); |
| 226 | } |
| 227 | void WebrtcVideoStream::OnChannelClosed( |
| 228 | ChannelDispatcherBase* channel_dispatcher) { |
| 229 | DCHECK(&video_stats_dispatcher_ == channel_dispatcher); |
| 230 | LOG(WARNING) << "video_stats channel was closed."; |
| 231 | } |
| 232 | |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 233 | void WebrtcVideoStream::CaptureNextFrame() { |
| 234 | DCHECK(thread_checker_.CalledOnValidThread()); |
| 235 | |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 236 | current_frame_stats_.reset(new FrameStats()); |
| 237 | current_frame_stats_->capture_started_time = base::TimeTicks::Now(); |
| 238 | current_frame_stats_->input_event_timestamps = |
sergeyu | 5e372bf | 2017-03-21 21:56:23 | [diff] [blame] | 239 | event_timestamps_source_->TakeLastEventTimestamps(); |
sergeyu | e84cc62 | 2016-10-15 06:54:03 | [diff] [blame] | 240 | |
zijiehe | 27bcc91 | 2016-10-18 05:57:56 | [diff] [blame] | 241 | capturer_->CaptureFrame(); |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 242 | } |
| 243 | |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 244 | void WebrtcVideoStream::OnFrameEncoded( |
Zijie He | cc8a077 | 2017-10-17 03:19:32 | [diff] [blame] | 245 | WebrtcVideoEncoder::EncodeResult encode_result, |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 246 | std::unique_ptr<WebrtcVideoEncoder::EncodedFrame> frame) { |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 247 | DCHECK(thread_checker_.CalledOnValidThread()); |
| 248 | |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 249 | current_frame_stats_->encode_ended_time = base::TimeTicks::Now(); |
sergeyu | 14b918b | 2017-01-09 23:10:24 | [diff] [blame] | 250 | |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 251 | HostFrameStats stats; |
| 252 | scheduler_->OnFrameEncoded(frame.get(), &stats); |
| 253 | |
Zijie He | cc8a077 | 2017-10-17 03:19:32 | [diff] [blame] | 254 | if (encode_result != WebrtcVideoEncoder::EncodeResult::SUCCEEDED) { |
Zijie He | cc8a077 | 2017-10-17 03:19:32 | [diff] [blame] | 255 | LOG(ERROR) << "Video encoder returns error " |
| 256 | << EncodeResultToString(encode_result); |
Zijie He | 3d3751dc | 2017-10-26 19:29:54 | [diff] [blame] | 257 | // TODO(zijiehe): Restart the video stream. |
| 258 | encoder_.reset(); |
Zijie He | cc8a077 | 2017-10-17 03:19:32 | [diff] [blame] | 259 | return; |
| 260 | } |
| 261 | |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 262 | if (!frame) { |
sergeyu | 14b918b | 2017-01-09 23:10:24 | [diff] [blame] | 263 | return; |
| 264 | } |
| 265 | |
sergeyu | 0eaa513 | 2016-09-20 01:39:34 | [diff] [blame] | 266 | webrtc::EncodedImageCallback::Result result = |
| 267 | webrtc_transport_->video_encoder_factory()->SendEncodedFrame( |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 268 | *frame, current_frame_stats_->capture_started_time); |
sergeyu | 0eaa513 | 2016-09-20 01:39:34 | [diff] [blame] | 269 | if (result.error != webrtc::EncodedImageCallback::Result::OK) { |
| 270 | // TODO(sergeyu): Stop the stream. |
| 271 | LOG(ERROR) << "Failed to send video frame."; |
| 272 | return; |
sergeyu | 0936463 | 2016-08-11 00:08:10 | [diff] [blame] | 273 | } |
| 274 | |
sergeyu | 0936463 | 2016-08-11 00:08:10 | [diff] [blame] | 275 | // Send FrameStats message. |
sergeyu | 0eaa513 | 2016-09-20 01:39:34 | [diff] [blame] | 276 | if (video_stats_dispatcher_.is_connected()) { |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 277 | stats.frame_size = frame ? frame->data.size() : 0; |
sergeyu | 4e10ab1 | 2016-06-22 00:56:22 | [diff] [blame] | 278 | |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 279 | if (!current_frame_stats_->input_event_timestamps.is_null()) { |
sergeyu | e84cc62 | 2016-10-15 06:54:03 | [diff] [blame] | 280 | stats.capture_pending_delay = |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 281 | current_frame_stats_->capture_started_time - |
| 282 | current_frame_stats_->input_event_timestamps.host_timestamp; |
sergeyu | e84cc62 | 2016-10-15 06:54:03 | [diff] [blame] | 283 | stats.latest_event_timestamp = |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 284 | current_frame_stats_->input_event_timestamps.client_timestamp; |
sergeyu | 0eaa513 | 2016-09-20 01:39:34 | [diff] [blame] | 285 | } |
| 286 | |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 287 | stats.capture_delay = current_frame_stats_->capture_delay; |
sergeyu | 0eaa513 | 2016-09-20 01:39:34 | [diff] [blame] | 288 | |
| 289 | // Total overhead time for IPC and threading when capturing frames. |
zijiehe | 805f2ca | 2017-03-27 00:56:00 | [diff] [blame] | 290 | stats.capture_overhead_delay = |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 291 | (current_frame_stats_->capture_ended_time - |
| 292 | current_frame_stats_->capture_started_time) - |
zijiehe | 805f2ca | 2017-03-27 00:56:00 | [diff] [blame] | 293 | stats.capture_delay; |
sergeyu | 0eaa513 | 2016-09-20 01:39:34 | [diff] [blame] | 294 | |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 295 | stats.encode_pending_delay = current_frame_stats_->encode_started_time - |
| 296 | current_frame_stats_->capture_ended_time; |
sergeyu | 0eaa513 | 2016-09-20 01:39:34 | [diff] [blame] | 297 | |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 298 | stats.encode_delay = current_frame_stats_->encode_ended_time - |
| 299 | current_frame_stats_->encode_started_time; |
zijiehe | 805f2ca | 2017-03-27 00:56:00 | [diff] [blame] | 300 | |
Sergey Ulanov | e50708f | 2017-06-20 21:29:11 | [diff] [blame] | 301 | stats.capturer_id = current_frame_stats_->capturer_id; |
sergeyu | 0eaa513 | 2016-09-20 01:39:34 | [diff] [blame] | 302 | |
sergeyu | 0eaa513 | 2016-09-20 01:39:34 | [diff] [blame] | 303 | video_stats_dispatcher_.OnVideoFrameStats(result.frame_id, stats); |
| 304 | } |
sergeyu | 0fc40f9 | 2015-12-10 18:42:43 | [diff] [blame] | 305 | } |
| 306 | |
yuweih | 1481d8d | 2017-04-04 01:43:51 | [diff] [blame] | 307 | void WebrtcVideoStream::OnEncoderCreated(webrtc::VideoCodecType codec_type) { |
| 308 | DCHECK(thread_checker_.CalledOnValidThread()); |
Zijie He | 3d3751dc | 2017-10-26 19:29:54 | [diff] [blame] | 309 | // The preferred codec id depends on the order of |
| 310 | // |encoder_selector_|.RegisterEncoder(). |
yuweih | 1481d8d | 2017-04-04 01:43:51 | [diff] [blame] | 311 | if (codec_type == webrtc::kVideoCodecVP8) { |
Zijie He | 3d3751dc | 2017-10-26 19:29:54 | [diff] [blame] | 312 | LOG(WARNING) << "VP8 video codec is preferred."; |
| 313 | encoder_selector_.SetPreferredCodec(0); |
yuweih | 1481d8d | 2017-04-04 01:43:51 | [diff] [blame] | 314 | } else if (codec_type == webrtc::kVideoCodecVP9) { |
Zijie He | 3d3751dc | 2017-10-26 19:29:54 | [diff] [blame] | 315 | LOG(WARNING) << "VP9 video codec is preferred."; |
| 316 | encoder_selector_.SetPreferredCodec(1); |
Gus Smith | b654f6fc | 2017-07-24 18:51:44 | [diff] [blame] | 317 | } else if (codec_type == webrtc::kVideoCodecH264) { |
Zijie He | caea1e4 | 2017-10-11 23:20:35 | [diff] [blame] | 318 | #if defined(USE_H264_ENCODER) |
Zijie He | 3d3751dc | 2017-10-26 19:29:54 | [diff] [blame] | 319 | LOG(WARNING) << "H264 video codec is preferred."; |
| 320 | encoder_selector_.SetPreferredCodec(2); |
Zijie He | caea1e4 | 2017-10-11 23:20:35 | [diff] [blame] | 321 | #else |
Gus Smith | b654f6fc | 2017-07-24 18:51:44 | [diff] [blame] | 322 | NOTIMPLEMENTED(); |
Zijie He | caea1e4 | 2017-10-11 23:20:35 | [diff] [blame] | 323 | #endif |
yuweih | 1481d8d | 2017-04-04 01:43:51 | [diff] [blame] | 324 | } else { |
| 325 | LOG(FATAL) << "Unknown codec type: " << codec_type; |
| 326 | } |
| 327 | } |
| 328 | |
sergeyu | 0fc40f9 | 2015-12-10 18:42:43 | [diff] [blame] | 329 | } // namespace protocol |
| 330 | } // namespace remoting |