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

Side by Side Diff: media/cast/video_sender/video_sender.cc

Issue 116623002: Cast: Adding support for GPU accelerated encode (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removed dependency on content Created 7 years 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 unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/cast/video_sender/video_sender.h" 5 #include "media/cast/video_sender/video_sender.h"
6 6
7 #include <list> 7 #include <list>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/message_loop/message_loop.h" 11 #include "base/message_loop/message_loop.h"
12 #include "crypto/encryptor.h" 12 #include "crypto/encryptor.h"
13 #include "crypto/symmetric_key.h" 13 #include "crypto/symmetric_key.h"
14 #include "media/cast/cast_defines.h" 14 #include "media/cast/cast_defines.h"
15 #include "media/cast/pacing/paced_sender.h" 15 #include "media/cast/pacing/paced_sender.h"
16 #include "media/cast/video_sender/video_encoder.h" 16 #include "media/cast/video_sender/external_video_encoder.h"
17 #include "media/cast/video_sender/video_encoder_impl.h"
17 18
18 namespace media { 19 namespace media {
19 namespace cast { 20 namespace cast {
20 21
21 const int64 kMinSchedulingDelayMs = 1; 22 const int64 kMinSchedulingDelayMs = 1;
22 23
23 class LocalRtcpVideoSenderFeedback : public RtcpSenderFeedback { 24 class LocalRtcpVideoSenderFeedback : public RtcpSenderFeedback {
24 public: 25 public:
25 explicit LocalRtcpVideoSenderFeedback(VideoSender* video_sender) 26 explicit LocalRtcpVideoSenderFeedback(VideoSender* video_sender)
26 : video_sender_(video_sender) { 27 : video_sender_(video_sender) {
(...skipping 19 matching lines...) Expand all
46 rtp_sender_->RtpStatistics(now, sender_info); 47 rtp_sender_->RtpStatistics(now, sender_info);
47 } 48 }
48 49
49 private: 50 private:
50 RtpSender* rtp_sender_; 51 RtpSender* rtp_sender_;
51 }; 52 };
52 53
53 VideoSender::VideoSender( 54 VideoSender::VideoSender(
54 scoped_refptr<CastEnvironment> cast_environment, 55 scoped_refptr<CastEnvironment> cast_environment,
55 const VideoSenderConfig& video_config, 56 const VideoSenderConfig& video_config,
56 VideoEncoderController* const video_encoder_controller, 57 const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories,
57 PacedPacketSender* const paced_packet_sender) 58 PacedPacketSender* const paced_packet_sender)
58 : rtp_max_delay_( 59 : rtp_max_delay_(
59 base::TimeDelta::FromMilliseconds(video_config.rtp_max_delay_ms)), 60 base::TimeDelta::FromMilliseconds(video_config.rtp_max_delay_ms)),
60 max_frame_rate_(video_config.max_frame_rate), 61 max_frame_rate_(video_config.max_frame_rate),
61 cast_environment_(cast_environment), 62 cast_environment_(cast_environment),
62 rtcp_feedback_(new LocalRtcpVideoSenderFeedback(this)), 63 rtcp_feedback_(new LocalRtcpVideoSenderFeedback(this)),
63 rtp_sender_(new RtpSender(cast_environment, NULL, &video_config, 64 rtp_sender_(new RtpSender(cast_environment, NULL, &video_config,
64 paced_packet_sender)), 65 paced_packet_sender)),
65 last_acked_frame_id_(-1), 66 last_acked_frame_id_(-1),
66 last_sent_frame_id_(-1), 67 last_sent_frame_id_(-1),
67 duplicate_ack_(0), 68 duplicate_ack_(0),
68 last_skip_count_(0), 69 last_skip_count_(0),
69 congestion_control_(cast_environment->Clock(), 70 congestion_control_(cast_environment->Clock(),
70 video_config.congestion_control_back_off, 71 video_config.congestion_control_back_off,
71 video_config.max_bitrate, 72 video_config.max_bitrate,
72 video_config.min_bitrate, 73 video_config.min_bitrate,
73 video_config.start_bitrate), 74 video_config.start_bitrate),
74 initialized_(false), 75 initialized_(false),
75 weak_factory_(this) { 76 weak_factory_(this) {
76 max_unacked_frames_ = static_cast<uint8>(video_config.rtp_max_delay_ms * 77 max_unacked_frames_ = static_cast<uint8>(video_config.rtp_max_delay_ms *
77 video_config.max_frame_rate / 1000) + 1; 78 video_config.max_frame_rate / 1000) + 1;
78 VLOG(1) << "max_unacked_frames " << static_cast<int>(max_unacked_frames_); 79 VLOG(1) << "max_unacked_frames " << static_cast<int>(max_unacked_frames_);
79 DCHECK_GT(max_unacked_frames_, 0) << "Invalid argument"; 80 DCHECK_GT(max_unacked_frames_, 0) << "Invalid argument";
80 81
81 rtp_video_sender_statistics_.reset( 82 rtp_video_sender_statistics_.reset(
82 new LocalRtpVideoSenderStatistics(rtp_sender_.get())); 83 new LocalRtpVideoSenderStatistics(rtp_sender_.get()));
83 84
84 if (video_config.use_external_encoder) { 85 if (video_config.use_external_encoder) {
85 DCHECK(video_encoder_controller) << "Invalid argument"; 86 video_encoder_.reset(new ExternalVideoEncoder(cast_environment,
86 video_encoder_controller_ = video_encoder_controller; 87 video_config, gpu_factories));
87 } else { 88 } else {
88 video_encoder_.reset(new VideoEncoder(cast_environment, video_config, 89 video_encoder_.reset(new VideoEncoderImpl(cast_environment, video_config,
89 max_unacked_frames_)); 90 max_unacked_frames_));
90 video_encoder_controller_ = video_encoder_.get();
91 } 91 }
92 92
93 if (video_config.aes_iv_mask.size() == kAesKeySize && 93 if (video_config.aes_iv_mask.size() == kAesKeySize &&
94 video_config.aes_key.size() == kAesKeySize) { 94 video_config.aes_key.size() == kAesKeySize) {
95 iv_mask_ = video_config.aes_iv_mask; 95 iv_mask_ = video_config.aes_iv_mask;
96 crypto::SymmetricKey* key = crypto::SymmetricKey::Import( 96 crypto::SymmetricKey* key = crypto::SymmetricKey::Import(
97 crypto::SymmetricKey::AES, video_config.aes_key); 97 crypto::SymmetricKey::AES, video_config.aes_key);
98 encryptor_.reset(new crypto::Encryptor()); 98 encryptor_.reset(new crypto::Encryptor());
99 encryptor_->Init(key, crypto::Encryptor::CTR, std::string()); 99 encryptor_->Init(key, crypto::Encryptor::CTR, std::string());
100 } else if (video_config.aes_iv_mask.size() != 0 || 100 } else if (video_config.aes_iv_mask.size() != 0 ||
101 video_config.aes_key.size() != 0) { 101 video_config.aes_key.size() != 0) {
102 DCHECK(false) << "Invalid crypto configuration"; 102 NOTREACHED() << "Invalid crypto configuration";
103 } 103 }
104 104
105 rtcp_.reset(new Rtcp( 105 rtcp_.reset(new Rtcp(
106 cast_environment_, 106 cast_environment_,
107 rtcp_feedback_.get(), 107 rtcp_feedback_.get(),
108 paced_packet_sender, 108 paced_packet_sender,
109 rtp_video_sender_statistics_.get(), 109 rtp_video_sender_statistics_.get(),
110 NULL, 110 NULL,
111 video_config.rtcp_mode, 111 video_config.rtcp_mode,
112 base::TimeDelta::FromMilliseconds(video_config.rtcp_interval), 112 base::TimeDelta::FromMilliseconds(video_config.rtcp_interval),
(...skipping 21 matching lines...) Expand all
134 DCHECK(video_encoder_.get()) << "Invalid state"; 134 DCHECK(video_encoder_.get()) << "Invalid state";
135 cast_environment_->Logging()->InsertFrameEvent(kVideoFrameReceived, 135 cast_environment_->Logging()->InsertFrameEvent(kVideoFrameReceived,
136 GetVideoRtpTimestamp(capture_time), kFrameIdUnknown); 136 GetVideoRtpTimestamp(capture_time), kFrameIdUnknown);
137 137
138 if (!video_encoder_->EncodeVideoFrame(video_frame, capture_time, 138 if (!video_encoder_->EncodeVideoFrame(video_frame, capture_time,
139 base::Bind(&VideoSender::SendEncodedVideoFrameMainThread, 139 base::Bind(&VideoSender::SendEncodedVideoFrameMainThread,
140 weak_factory_.GetWeakPtr()))) { 140 weak_factory_.GetWeakPtr()))) {
141 } 141 }
142 } 142 }
143 143
144 void VideoSender::InsertCodedVideoFrame(const EncodedVideoFrame* encoded_frame,
145 const base::TimeTicks& capture_time,
146 const base::Closure callback) {
147 DCHECK(!video_encoder_.get()) << "Invalid state";
148 DCHECK(encoded_frame) << "Invalid argument";
149 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
150
151 SendEncodedVideoFrame(encoded_frame, capture_time);
152 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, callback);
153 }
154
155 void VideoSender::SendEncodedVideoFrameMainThread( 144 void VideoSender::SendEncodedVideoFrameMainThread(
156 scoped_ptr<EncodedVideoFrame> video_frame, 145 scoped_ptr<EncodedVideoFrame> video_frame,
157 const base::TimeTicks& capture_time) { 146 const base::TimeTicks& capture_time) {
158 SendEncodedVideoFrame(video_frame.get(), capture_time); 147 SendEncodedVideoFrame(video_frame.get(), capture_time);
159 } 148 }
160 149
161 bool VideoSender::EncryptVideoFrame(const EncodedVideoFrame& video_frame, 150 bool VideoSender::EncryptVideoFrame(const EncodedVideoFrame& video_frame,
162 EncodedVideoFrame* encrypted_frame) { 151 EncodedVideoFrame* encrypted_frame) {
163 DCHECK(encryptor_) << "Invalid state"; 152 DCHECK(encryptor_) << "Invalid state";
164 153
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 } 238 }
250 239
251 void VideoSender::ResendCheck() { 240 void VideoSender::ResendCheck() {
252 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 241 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
253 if (!last_send_time_.is_null() && last_sent_frame_id_ != -1) { 242 if (!last_send_time_.is_null() && last_sent_frame_id_ != -1) {
254 base::TimeDelta time_since_last_send = 243 base::TimeDelta time_since_last_send =
255 cast_environment_->Clock()->NowTicks() - last_send_time_; 244 cast_environment_->Clock()->NowTicks() - last_send_time_;
256 if (time_since_last_send > rtp_max_delay_) { 245 if (time_since_last_send > rtp_max_delay_) {
257 if (last_acked_frame_id_ == -1) { 246 if (last_acked_frame_id_ == -1) {
258 // We have not received any ack, send a key frame. 247 // We have not received any ack, send a key frame.
259 video_encoder_controller_->GenerateKeyFrame(); 248 video_encoder_->GenerateKeyFrame();
260 last_acked_frame_id_ = -1; 249 last_acked_frame_id_ = -1;
261 last_sent_frame_id_ = -1; 250 last_sent_frame_id_ = -1;
262 UpdateFramesInFlight(); 251 UpdateFramesInFlight();
263 } else { 252 } else {
264 DCHECK_LE(0, last_acked_frame_id_); 253 DCHECK_LE(0, last_acked_frame_id_);
265 254
266 uint32 frame_id = static_cast<uint32>(last_acked_frame_id_ + 1); 255 uint32 frame_id = static_cast<uint32>(last_acked_frame_id_ + 1);
267 VLOG(1) << "ACK timeout resend frame:" << static_cast<int>(frame_id); 256 VLOG(1) << "ACK timeout resend frame:" << static_cast<int>(frame_id);
268 ResendFrame(frame_id); 257 ResendFrame(frame_id);
269 } 258 }
(...skipping 16 matching lines...) Expand all
286 time_to_next = std::max(time_to_next, 275 time_to_next = std::max(time_to_next,
287 base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); 276 base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs));
288 277
289 cast_environment_->PostDelayedTask(CastEnvironment::MAIN, FROM_HERE, 278 cast_environment_->PostDelayedTask(CastEnvironment::MAIN, FROM_HERE,
290 base::Bind(&VideoSender::SkippedFramesCheck, weak_factory_.GetWeakPtr()), 279 base::Bind(&VideoSender::SkippedFramesCheck, weak_factory_.GetWeakPtr()),
291 time_to_next); 280 time_to_next);
292 } 281 }
293 282
294 void VideoSender::SkippedFramesCheck() { 283 void VideoSender::SkippedFramesCheck() {
295 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 284 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
296 int skip_count = video_encoder_controller_->NumberOfSkippedFrames(); 285 int skip_count = video_encoder_->NumberOfSkippedFrames();
297 if (skip_count - last_skip_count_ > 286 if (skip_count - last_skip_count_ >
298 kSkippedFramesThreshold * max_frame_rate_) { 287 kSkippedFramesThreshold * max_frame_rate_) {
299 // TODO(pwestin): Propagate this up to the application. 288 // TODO(pwestin): Propagate this up to the application.
300 } 289 }
301 last_skip_count_ = skip_count; 290 last_skip_count_ = skip_count;
302 last_checked_skip_count_time_ = cast_environment_->Clock()->NowTicks(); 291 last_checked_skip_count_time_ = cast_environment_->Clock()->NowTicks();
303 ScheduleNextSkippedFramesCheck(); 292 ScheduleNextSkippedFramesCheck();
304 } 293 }
305 294
306 void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { 295 void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) {
(...skipping 10 matching lines...) Expand all
317 rtt = std::max(rtt, avg_rtt); 306 rtt = std::max(rtt, avg_rtt);
318 } else { 307 } else {
319 // We have no measured value use default. 308 // We have no measured value use default.
320 rtt = base::TimeDelta::FromMilliseconds(kStartRttMs); 309 rtt = base::TimeDelta::FromMilliseconds(kStartRttMs);
321 } 310 }
322 if (cast_feedback.missing_frames_and_packets_.empty()) { 311 if (cast_feedback.missing_frames_and_packets_.empty()) {
323 // No lost packets. 312 // No lost packets.
324 int resend_frame = -1; 313 int resend_frame = -1;
325 if (last_sent_frame_id_ == -1) return; 314 if (last_sent_frame_id_ == -1) return;
326 315
327 video_encoder_controller_->LatestFrameIdToReference( 316 video_encoder_->LatestFrameIdToReference(
328 cast_feedback.ack_frame_id_); 317 cast_feedback.ack_frame_id_);
329 318
330 if (static_cast<uint32>(last_acked_frame_id_ + 1) == 319 if (static_cast<uint32>(last_acked_frame_id_ + 1) ==
331 cast_feedback.ack_frame_id_) { 320 cast_feedback.ack_frame_id_) {
332 uint32 new_bitrate = 0; 321 uint32 new_bitrate = 0;
333 if (congestion_control_.OnAck(rtt, &new_bitrate)) { 322 if (congestion_control_.OnAck(rtt, &new_bitrate)) {
334 video_encoder_controller_->SetBitRate(new_bitrate); 323 video_encoder_->SetBitRate(new_bitrate);
335 } 324 }
336 } 325 }
337 if (static_cast<uint32>(last_acked_frame_id_) == cast_feedback.ack_frame_id_ 326 if (static_cast<uint32>(last_acked_frame_id_) == cast_feedback.ack_frame_id_
338 // We only count duplicate ACKs when we have sent newer frames. 327 // We only count duplicate ACKs when we have sent newer frames.
339 && IsNewerFrameId(last_sent_frame_id_, last_acked_frame_id_)) { 328 && IsNewerFrameId(last_sent_frame_id_, last_acked_frame_id_)) {
340 duplicate_ack_++; 329 duplicate_ack_++;
341 } else { 330 } else {
342 duplicate_ack_ = 0; 331 duplicate_ack_ = 0;
343 } 332 }
344 if (duplicate_ack_ >= 2 && duplicate_ack_ % 3 == 2) { 333 if (duplicate_ack_ >= 2 && duplicate_ack_ % 3 == 2) {
345 // Resend last ACK + 1 frame. 334 // Resend last ACK + 1 frame.
346 resend_frame = static_cast<uint32>(last_acked_frame_id_ + 1); 335 resend_frame = static_cast<uint32>(last_acked_frame_id_ + 1);
347 } 336 }
348 if (resend_frame != -1) { 337 if (resend_frame != -1) {
349 DCHECK_LE(0, resend_frame); 338 DCHECK_LE(0, resend_frame);
350 VLOG(1) << "Received duplicate ACK for frame:" 339 VLOG(1) << "Received duplicate ACK for frame:"
351 << static_cast<int>(resend_frame); 340 << static_cast<int>(resend_frame);
352 ResendFrame(static_cast<uint32>(resend_frame)); 341 ResendFrame(static_cast<uint32>(resend_frame));
353 } 342 }
354 } else { 343 } else {
355 rtp_sender_->ResendPackets(cast_feedback.missing_frames_and_packets_); 344 rtp_sender_->ResendPackets(cast_feedback.missing_frames_and_packets_);
356 last_send_time_ = cast_environment_->Clock()->NowTicks(); 345 last_send_time_ = cast_environment_->Clock()->NowTicks();
357 346
358 uint32 new_bitrate = 0; 347 uint32 new_bitrate = 0;
359 if (congestion_control_.OnNack(rtt, &new_bitrate)) { 348 if (congestion_control_.OnNack(rtt, &new_bitrate)) {
360 video_encoder_controller_->SetBitRate(new_bitrate); 349 video_encoder_->SetBitRate(new_bitrate);
361 } 350 }
362 } 351 }
363 ReceivedAck(cast_feedback.ack_frame_id_); 352 ReceivedAck(cast_feedback.ack_frame_id_);
364 } 353 }
365 354
366 void VideoSender::ReceivedAck(uint32 acked_frame_id) { 355 void VideoSender::ReceivedAck(uint32 acked_frame_id) {
367 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 356 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
368 last_acked_frame_id_ = static_cast<int>(acked_frame_id); 357 last_acked_frame_id_ = static_cast<int>(acked_frame_id);
369 cast_environment_->Logging()->InsertGenericEvent(kAckReceived, 358 cast_environment_->Logging()->InsertGenericEvent(kAckReceived,
370 acked_frame_id); 359 acked_frame_id);
(...skipping 10 matching lines...) Expand all
381 if (last_acked_frame_id_ != -1) { 370 if (last_acked_frame_id_ != -1) {
382 DCHECK_LE(0, last_acked_frame_id_); 371 DCHECK_LE(0, last_acked_frame_id_);
383 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) - 372 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) -
384 static_cast<uint32>(last_acked_frame_id_); 373 static_cast<uint32>(last_acked_frame_id_);
385 } else { 374 } else {
386 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) + 1; 375 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) + 1;
387 } 376 }
388 VLOG(1) << "Frames in flight; last sent: " << last_sent_frame_id_ 377 VLOG(1) << "Frames in flight; last sent: " << last_sent_frame_id_
389 << " last acked:" << last_acked_frame_id_; 378 << " last acked:" << last_acked_frame_id_;
390 if (frames_in_flight >= max_unacked_frames_) { 379 if (frames_in_flight >= max_unacked_frames_) {
391 video_encoder_controller_->SkipNextFrame(true); 380 video_encoder_->SkipNextFrame(true);
392 return; 381 return;
393 } 382 }
394 } 383 }
395 video_encoder_controller_->SkipNextFrame(false); 384 video_encoder_->SkipNextFrame(false);
396 } 385 }
397 386
398 void VideoSender::ResendFrame(uint32 resend_frame_id) { 387 void VideoSender::ResendFrame(uint32 resend_frame_id) {
399 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 388 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
400 MissingFramesAndPacketsMap missing_frames_and_packets; 389 MissingFramesAndPacketsMap missing_frames_and_packets;
401 PacketIdSet missing; 390 PacketIdSet missing;
402 missing_frames_and_packets.insert(std::make_pair(resend_frame_id, missing)); 391 missing_frames_and_packets.insert(std::make_pair(resend_frame_id, missing));
403 rtp_sender_->ResendPackets(missing_frames_and_packets); 392 rtp_sender_->ResendPackets(missing_frames_and_packets);
404 last_send_time_ = cast_environment_->Clock()->NowTicks(); 393 last_send_time_ = cast_environment_->Clock()->NowTicks();
405 } 394 }
406 395
407 } // namespace cast 396 } // namespace cast
408 } // namespace media 397 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698