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

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: Cleanup 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 // Query media::VideoEncodeAccelerator (statically) for our supported
86 video_encoder_controller_ = video_encoder_controller; 87 // codecs.
88 std::vector<media::VideoEncodeAccelerator::SupportedProfile> profiles =
89 content::GpuVideoEncodeAcceleratorHost::GetSupportedProfiles();
90 DCHECK(profiles.empty()) << "No hardware support";
91 for (size_t i = 0; i < profiles.size(); ++i) {
92 // TODO(pwestin): verify codecs.
93 }
94 video_encoder_.reset(new ExternalVideoEncoder(cast_environment,
95 video_config, gpu_factories));
87 } else { 96 } else {
88 video_encoder_.reset(new VideoEncoder(cast_environment, video_config, 97 video_encoder_.reset(new VideoEncoderImpl(cast_environment, video_config,
89 max_unacked_frames_)); 98 max_unacked_frames_));
90 video_encoder_controller_ = video_encoder_.get();
91 } 99 }
92 100
93 if (video_config.aes_iv_mask.size() == kAesKeySize && 101 if (video_config.aes_iv_mask.size() == kAesKeySize &&
94 video_config.aes_key.size() == kAesKeySize) { 102 video_config.aes_key.size() == kAesKeySize) {
95 iv_mask_ = video_config.aes_iv_mask; 103 iv_mask_ = video_config.aes_iv_mask;
96 crypto::SymmetricKey* key = crypto::SymmetricKey::Import( 104 crypto::SymmetricKey* key = crypto::SymmetricKey::Import(
97 crypto::SymmetricKey::AES, video_config.aes_key); 105 crypto::SymmetricKey::AES, video_config.aes_key);
98 encryptor_.reset(new crypto::Encryptor()); 106 encryptor_.reset(new crypto::Encryptor());
99 encryptor_->Init(key, crypto::Encryptor::CTR, std::string()); 107 encryptor_->Init(key, crypto::Encryptor::CTR, std::string());
100 } else if (video_config.aes_iv_mask.size() != 0 || 108 } else if (video_config.aes_iv_mask.size() != 0 ||
101 video_config.aes_key.size() != 0) { 109 video_config.aes_key.size() != 0) {
102 DCHECK(false) << "Invalid crypto configuration"; 110 NOTREACHED() << "Invalid crypto configuration";
103 } 111 }
104 112
105 rtcp_.reset(new Rtcp( 113 rtcp_.reset(new Rtcp(
106 cast_environment_, 114 cast_environment_,
107 rtcp_feedback_.get(), 115 rtcp_feedback_.get(),
108 paced_packet_sender, 116 paced_packet_sender,
109 rtp_video_sender_statistics_.get(), 117 rtp_video_sender_statistics_.get(),
110 NULL, 118 NULL,
111 video_config.rtcp_mode, 119 video_config.rtcp_mode,
112 base::TimeDelta::FromMilliseconds(video_config.rtcp_interval), 120 base::TimeDelta::FromMilliseconds(video_config.rtcp_interval),
(...skipping 21 matching lines...) Expand all
134 DCHECK(video_encoder_.get()) << "Invalid state"; 142 DCHECK(video_encoder_.get()) << "Invalid state";
135 cast_environment_->Logging()->InsertFrameEvent(kVideoFrameReceived, 143 cast_environment_->Logging()->InsertFrameEvent(kVideoFrameReceived,
136 GetVideoRtpTimestamp(capture_time), kFrameIdUnknown); 144 GetVideoRtpTimestamp(capture_time), kFrameIdUnknown);
137 145
138 if (!video_encoder_->EncodeVideoFrame(video_frame, capture_time, 146 if (!video_encoder_->EncodeVideoFrame(video_frame, capture_time,
139 base::Bind(&VideoSender::SendEncodedVideoFrameMainThread, 147 base::Bind(&VideoSender::SendEncodedVideoFrameMainThread,
140 weak_factory_.GetWeakPtr()))) { 148 weak_factory_.GetWeakPtr()))) {
141 } 149 }
142 } 150 }
143 151
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( 152 void VideoSender::SendEncodedVideoFrameMainThread(
156 scoped_ptr<EncodedVideoFrame> video_frame, 153 scoped_ptr<EncodedVideoFrame> video_frame,
157 const base::TimeTicks& capture_time) { 154 const base::TimeTicks& capture_time) {
158 SendEncodedVideoFrame(video_frame.get(), capture_time); 155 SendEncodedVideoFrame(video_frame.get(), capture_time);
159 } 156 }
160 157
161 bool VideoSender::EncryptVideoFrame(const EncodedVideoFrame& video_frame, 158 bool VideoSender::EncryptVideoFrame(const EncodedVideoFrame& video_frame,
162 EncodedVideoFrame* encrypted_frame) { 159 EncodedVideoFrame* encrypted_frame) {
163 DCHECK(encryptor_) << "Invalid state"; 160 DCHECK(encryptor_) << "Invalid state";
164 161
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 } 246 }
250 247
251 void VideoSender::ResendCheck() { 248 void VideoSender::ResendCheck() {
252 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 249 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
253 if (!last_send_time_.is_null() && last_sent_frame_id_ != -1) { 250 if (!last_send_time_.is_null() && last_sent_frame_id_ != -1) {
254 base::TimeDelta time_since_last_send = 251 base::TimeDelta time_since_last_send =
255 cast_environment_->Clock()->NowTicks() - last_send_time_; 252 cast_environment_->Clock()->NowTicks() - last_send_time_;
256 if (time_since_last_send > rtp_max_delay_) { 253 if (time_since_last_send > rtp_max_delay_) {
257 if (last_acked_frame_id_ == -1) { 254 if (last_acked_frame_id_ == -1) {
258 // We have not received any ack, send a key frame. 255 // We have not received any ack, send a key frame.
259 video_encoder_controller_->GenerateKeyFrame(); 256 video_encoder_->GenerateKeyFrame();
260 last_acked_frame_id_ = -1; 257 last_acked_frame_id_ = -1;
261 last_sent_frame_id_ = -1; 258 last_sent_frame_id_ = -1;
262 UpdateFramesInFlight(); 259 UpdateFramesInFlight();
263 } else { 260 } else {
264 DCHECK_LE(0, last_acked_frame_id_); 261 DCHECK_LE(0, last_acked_frame_id_);
265 262
266 uint32 frame_id = static_cast<uint32>(last_acked_frame_id_ + 1); 263 uint32 frame_id = static_cast<uint32>(last_acked_frame_id_ + 1);
267 VLOG(1) << "ACK timeout resend frame:" << static_cast<int>(frame_id); 264 VLOG(1) << "ACK timeout resend frame:" << static_cast<int>(frame_id);
268 ResendFrame(frame_id); 265 ResendFrame(frame_id);
269 } 266 }
(...skipping 16 matching lines...) Expand all
286 time_to_next = std::max(time_to_next, 283 time_to_next = std::max(time_to_next,
287 base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); 284 base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs));
288 285
289 cast_environment_->PostDelayedTask(CastEnvironment::MAIN, FROM_HERE, 286 cast_environment_->PostDelayedTask(CastEnvironment::MAIN, FROM_HERE,
290 base::Bind(&VideoSender::SkippedFramesCheck, weak_factory_.GetWeakPtr()), 287 base::Bind(&VideoSender::SkippedFramesCheck, weak_factory_.GetWeakPtr()),
291 time_to_next); 288 time_to_next);
292 } 289 }
293 290
294 void VideoSender::SkippedFramesCheck() { 291 void VideoSender::SkippedFramesCheck() {
295 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 292 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
296 int skip_count = video_encoder_controller_->NumberOfSkippedFrames(); 293 int skip_count = video_encoder_->NumberOfSkippedFrames();
297 if (skip_count - last_skip_count_ > 294 if (skip_count - last_skip_count_ >
298 kSkippedFramesThreshold * max_frame_rate_) { 295 kSkippedFramesThreshold * max_frame_rate_) {
299 // TODO(pwestin): Propagate this up to the application. 296 // TODO(pwestin): Propagate this up to the application.
300 } 297 }
301 last_skip_count_ = skip_count; 298 last_skip_count_ = skip_count;
302 last_checked_skip_count_time_ = cast_environment_->Clock()->NowTicks(); 299 last_checked_skip_count_time_ = cast_environment_->Clock()->NowTicks();
303 ScheduleNextSkippedFramesCheck(); 300 ScheduleNextSkippedFramesCheck();
304 } 301 }
305 302
306 void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { 303 void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) {
(...skipping 10 matching lines...) Expand all
317 rtt = std::max(rtt, avg_rtt); 314 rtt = std::max(rtt, avg_rtt);
318 } else { 315 } else {
319 // We have no measured value use default. 316 // We have no measured value use default.
320 rtt = base::TimeDelta::FromMilliseconds(kStartRttMs); 317 rtt = base::TimeDelta::FromMilliseconds(kStartRttMs);
321 } 318 }
322 if (cast_feedback.missing_frames_and_packets_.empty()) { 319 if (cast_feedback.missing_frames_and_packets_.empty()) {
323 // No lost packets. 320 // No lost packets.
324 int resend_frame = -1; 321 int resend_frame = -1;
325 if (last_sent_frame_id_ == -1) return; 322 if (last_sent_frame_id_ == -1) return;
326 323
327 video_encoder_controller_->LatestFrameIdToReference( 324 video_encoder_->LatestFrameIdToReference(
328 cast_feedback.ack_frame_id_); 325 cast_feedback.ack_frame_id_);
329 326
330 if (static_cast<uint32>(last_acked_frame_id_ + 1) == 327 if (static_cast<uint32>(last_acked_frame_id_ + 1) ==
331 cast_feedback.ack_frame_id_) { 328 cast_feedback.ack_frame_id_) {
332 uint32 new_bitrate = 0; 329 uint32 new_bitrate = 0;
333 if (congestion_control_.OnAck(rtt, &new_bitrate)) { 330 if (congestion_control_.OnAck(rtt, &new_bitrate)) {
334 video_encoder_controller_->SetBitRate(new_bitrate); 331 video_encoder_->SetBitRate(new_bitrate);
335 } 332 }
336 } 333 }
337 if (static_cast<uint32>(last_acked_frame_id_) == cast_feedback.ack_frame_id_ 334 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. 335 // We only count duplicate ACKs when we have sent newer frames.
339 && IsNewerFrameId(last_sent_frame_id_, last_acked_frame_id_)) { 336 && IsNewerFrameId(last_sent_frame_id_, last_acked_frame_id_)) {
340 duplicate_ack_++; 337 duplicate_ack_++;
341 } else { 338 } else {
342 duplicate_ack_ = 0; 339 duplicate_ack_ = 0;
343 } 340 }
344 if (duplicate_ack_ >= 2 && duplicate_ack_ % 3 == 2) { 341 if (duplicate_ack_ >= 2 && duplicate_ack_ % 3 == 2) {
345 // Resend last ACK + 1 frame. 342 // Resend last ACK + 1 frame.
346 resend_frame = static_cast<uint32>(last_acked_frame_id_ + 1); 343 resend_frame = static_cast<uint32>(last_acked_frame_id_ + 1);
347 } 344 }
348 if (resend_frame != -1) { 345 if (resend_frame != -1) {
349 DCHECK_LE(0, resend_frame); 346 DCHECK_LE(0, resend_frame);
350 VLOG(1) << "Received duplicate ACK for frame:" 347 VLOG(1) << "Received duplicate ACK for frame:"
351 << static_cast<int>(resend_frame); 348 << static_cast<int>(resend_frame);
352 ResendFrame(static_cast<uint32>(resend_frame)); 349 ResendFrame(static_cast<uint32>(resend_frame));
353 } 350 }
354 } else { 351 } else {
355 rtp_sender_->ResendPackets(cast_feedback.missing_frames_and_packets_); 352 rtp_sender_->ResendPackets(cast_feedback.missing_frames_and_packets_);
356 last_send_time_ = cast_environment_->Clock()->NowTicks(); 353 last_send_time_ = cast_environment_->Clock()->NowTicks();
357 354
358 uint32 new_bitrate = 0; 355 uint32 new_bitrate = 0;
359 if (congestion_control_.OnNack(rtt, &new_bitrate)) { 356 if (congestion_control_.OnNack(rtt, &new_bitrate)) {
360 video_encoder_controller_->SetBitRate(new_bitrate); 357 video_encoder_->SetBitRate(new_bitrate);
361 } 358 }
362 } 359 }
363 ReceivedAck(cast_feedback.ack_frame_id_); 360 ReceivedAck(cast_feedback.ack_frame_id_);
364 } 361 }
365 362
366 void VideoSender::ReceivedAck(uint32 acked_frame_id) { 363 void VideoSender::ReceivedAck(uint32 acked_frame_id) {
367 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 364 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
368 last_acked_frame_id_ = static_cast<int>(acked_frame_id); 365 last_acked_frame_id_ = static_cast<int>(acked_frame_id);
369 cast_environment_->Logging()->InsertGenericEvent(kAckReceived, 366 cast_environment_->Logging()->InsertGenericEvent(kAckReceived,
370 acked_frame_id); 367 acked_frame_id);
(...skipping 10 matching lines...) Expand all
381 if (last_acked_frame_id_ != -1) { 378 if (last_acked_frame_id_ != -1) {
382 DCHECK_LE(0, last_acked_frame_id_); 379 DCHECK_LE(0, last_acked_frame_id_);
383 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) - 380 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) -
384 static_cast<uint32>(last_acked_frame_id_); 381 static_cast<uint32>(last_acked_frame_id_);
385 } else { 382 } else {
386 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) + 1; 383 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) + 1;
387 } 384 }
388 VLOG(1) << "Frames in flight; last sent: " << last_sent_frame_id_ 385 VLOG(1) << "Frames in flight; last sent: " << last_sent_frame_id_
389 << " last acked:" << last_acked_frame_id_; 386 << " last acked:" << last_acked_frame_id_;
390 if (frames_in_flight >= max_unacked_frames_) { 387 if (frames_in_flight >= max_unacked_frames_) {
391 video_encoder_controller_->SkipNextFrame(true); 388 video_encoder_->SkipNextFrame(true);
392 return; 389 return;
393 } 390 }
394 } 391 }
395 video_encoder_controller_->SkipNextFrame(false); 392 video_encoder_->SkipNextFrame(false);
396 } 393 }
397 394
398 void VideoSender::ResendFrame(uint32 resend_frame_id) { 395 void VideoSender::ResendFrame(uint32 resend_frame_id) {
399 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 396 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
400 MissingFramesAndPacketsMap missing_frames_and_packets; 397 MissingFramesAndPacketsMap missing_frames_and_packets;
401 PacketIdSet missing; 398 PacketIdSet missing;
402 missing_frames_and_packets.insert(std::make_pair(resend_frame_id, missing)); 399 missing_frames_and_packets.insert(std::make_pair(resend_frame_id, missing));
403 rtp_sender_->ResendPackets(missing_frames_and_packets); 400 rtp_sender_->ResendPackets(missing_frames_and_packets);
404 last_send_time_ = cast_environment_->Clock()->NowTicks(); 401 last_send_time_ = cast_environment_->Clock()->NowTicks();
405 } 402 }
406 403
407 } // namespace cast 404 } // namespace cast
408 } // namespace media 405 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698