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

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

Issue 252923007: Cast: Fix two video freezing problems (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: hide max outstanding frames from cast library users Created 6 years, 7 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 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 <cstring> 7 #include <cstring>
8 #include <list> 8 #include <list>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 : rtp_max_delay_(base::TimeDelta::FromMilliseconds( 54 : rtp_max_delay_(base::TimeDelta::FromMilliseconds(
55 video_config.rtp_config.max_delay_ms)), 55 video_config.rtp_config.max_delay_ms)),
56 max_frame_rate_(video_config.max_frame_rate), 56 max_frame_rate_(video_config.max_frame_rate),
57 cast_environment_(cast_environment), 57 cast_environment_(cast_environment),
58 transport_sender_(transport_sender), 58 transport_sender_(transport_sender),
59 event_subscriber_(kMaxEventSubscriberEntries), 59 event_subscriber_(kMaxEventSubscriberEntries),
60 rtp_stats_(kVideoFrequency), 60 rtp_stats_(kVideoFrequency),
61 rtcp_feedback_(new LocalRtcpVideoSenderFeedback(this)), 61 rtcp_feedback_(new LocalRtcpVideoSenderFeedback(this)),
62 last_acked_frame_id_(-1), 62 last_acked_frame_id_(-1),
63 last_sent_frame_id_(-1), 63 last_sent_frame_id_(-1),
64 frames_in_encoder_(0),
64 duplicate_ack_(0), 65 duplicate_ack_(0),
65 last_skip_count_(0), 66 last_skip_count_(0),
66 current_requested_bitrate_(video_config.start_bitrate), 67 current_requested_bitrate_(video_config.start_bitrate),
67 congestion_control_(cast_environment->Clock(), 68 congestion_control_(cast_environment->Clock(),
68 video_config.congestion_control_back_off, 69 video_config.congestion_control_back_off,
69 video_config.max_bitrate, 70 video_config.max_bitrate,
70 video_config.min_bitrate, 71 video_config.min_bitrate,
71 video_config.start_bitrate), 72 video_config.start_bitrate),
72 initialized_(false), 73 initialized_(false),
73 active_session_(false), 74 active_session_(false),
74 weak_factory_(this) { 75 weak_factory_(this) {
75 max_unacked_frames_ = 76 max_unacked_frames_ =
76 1 + static_cast<uint8>(video_config.rtp_config.max_delay_ms * 77 1 + static_cast<uint8>(video_config.rtp_config.max_delay_ms *
77 max_frame_rate_ / 1000); 78 max_frame_rate_ / 1000);
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 if (video_config.use_external_encoder) { 82 if (video_config.use_external_encoder) {
82 video_encoder_.reset(new ExternalVideoEncoder(cast_environment, 83 video_encoder_.reset(new ExternalVideoEncoder(cast_environment,
83 video_config, 84 video_config,
84 create_vea_cb, 85 create_vea_cb,
85 create_video_encode_mem_cb)); 86 create_video_encode_mem_cb));
86 } else { 87 } else {
87 video_encoder_.reset(new VideoEncoderImpl( 88 video_encoder_.reset(new VideoEncoderImpl(
88 cast_environment, video_config, max_unacked_frames_)); 89 cast_environment, video_config, max_unacked_frames_));
89 } 90 }
90 91
92
93 media::cast::transport::CastTransportVideoConfig transport_config;
94 transport_config.codec = video_config.codec;
95 transport_config.rtp.config = video_config.rtp_config;
96 transport_config.rtp.max_outstanding_frames = max_unacked_frames_ + 1;
97 transport_sender_->InitializeVideo(transport_config);
98
91 rtcp_.reset( 99 rtcp_.reset(
92 new Rtcp(cast_environment_, 100 new Rtcp(cast_environment_,
93 rtcp_feedback_.get(), 101 rtcp_feedback_.get(),
94 transport_sender_, 102 transport_sender_,
95 NULL, // paced sender. 103 NULL, // paced sender.
96 NULL, 104 NULL,
97 video_config.rtcp_mode, 105 video_config.rtcp_mode,
98 base::TimeDelta::FromMilliseconds(video_config.rtcp_interval), 106 base::TimeDelta::FromMilliseconds(video_config.rtcp_interval),
99 video_config.sender_ssrc, 107 video_config.rtp_config.ssrc,
100 video_config.incoming_feedback_ssrc, 108 video_config.incoming_feedback_ssrc,
101 video_config.rtcp_c_name)); 109 video_config.rtcp_c_name));
102 rtcp_->SetCastReceiverEventHistorySize(kReceiverRtcpEventHistorySize); 110 rtcp_->SetCastReceiverEventHistorySize(kReceiverRtcpEventHistorySize);
103 111
104 // TODO(pwestin): pass cast_initialization_cb to |video_encoder_| 112 // TODO(pwestin): pass cast_initialization_cb to |video_encoder_|
105 // and remove this call. 113 // and remove this call.
106 cast_environment_->PostTask( 114 cast_environment_->PostTask(
107 CastEnvironment::MAIN, 115 CastEnvironment::MAIN,
108 FROM_HERE, 116 FROM_HERE,
109 base::Bind(cast_initialization_cb, STATUS_VIDEO_INITIALIZED)); 117 base::Bind(cast_initialization_cb, STATUS_VIDEO_INITIALIZED));
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 rtp_timestamp, 151 rtp_timestamp,
144 kFrameIdUnknown); 152 kFrameIdUnknown);
145 153
146 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc 154 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc
147 TRACE_EVENT_INSTANT2( 155 TRACE_EVENT_INSTANT2(
148 "cast_perf_test", "InsertRawVideoFrame", 156 "cast_perf_test", "InsertRawVideoFrame",
149 TRACE_EVENT_SCOPE_THREAD, 157 TRACE_EVENT_SCOPE_THREAD,
150 "timestamp", capture_time.ToInternalValue(), 158 "timestamp", capture_time.ToInternalValue(),
151 "rtp_timestamp", GetVideoRtpTimestamp(capture_time)); 159 "rtp_timestamp", GetVideoRtpTimestamp(capture_time));
152 160
153 if (!video_encoder_->EncodeVideoFrame( 161 if (video_encoder_->EncodeVideoFrame(
154 video_frame, 162 video_frame,
155 capture_time, 163 capture_time,
156 base::Bind(&VideoSender::SendEncodedVideoFrameMainThread, 164 base::Bind(&VideoSender::SendEncodedVideoFrameMainThread,
157 weak_factory_.GetWeakPtr()))) { 165 weak_factory_.GetWeakPtr()))) {
166 frames_in_encoder_++;
167 UpdateFramesInFlight();
158 } 168 }
159 } 169 }
160 170
161 void VideoSender::SendEncodedVideoFrameMainThread( 171 void VideoSender::SendEncodedVideoFrameMainThread(
162 scoped_ptr<transport::EncodedVideoFrame> encoded_frame, 172 scoped_ptr<transport::EncodedVideoFrame> encoded_frame,
163 const base::TimeTicks& capture_time) { 173 const base::TimeTicks& capture_time) {
164 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 174 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
165 last_send_time_ = cast_environment_->Clock()->NowTicks(); 175 last_send_time_ = cast_environment_->Clock()->NowTicks();
166 if (encoded_frame->key_frame) { 176 if (encoded_frame->key_frame) {
167 VLOG(1) << "Send encoded key frame; frame_id:" 177 VLOG(1) << "Send encoded key frame; frame_id:"
168 << static_cast<int>(encoded_frame->frame_id); 178 << static_cast<int>(encoded_frame->frame_id);
169 } 179 }
170 180
181 DCHECK_GT(frames_in_encoder_, 0);
182 frames_in_encoder_--;
171 uint32 frame_id = encoded_frame->frame_id; 183 uint32 frame_id = encoded_frame->frame_id;
172 cast_environment_->Logging()->InsertEncodedFrameEvent( 184 cast_environment_->Logging()->InsertEncodedFrameEvent(
173 last_send_time_, kVideoFrameEncoded, encoded_frame->rtp_timestamp, 185 last_send_time_, kVideoFrameEncoded, encoded_frame->rtp_timestamp,
174 frame_id, static_cast<int>(encoded_frame->data.size()), 186 frame_id, static_cast<int>(encoded_frame->data.size()),
175 encoded_frame->key_frame, current_requested_bitrate_); 187 encoded_frame->key_frame, current_requested_bitrate_);
176 188
177 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc 189 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc
178 TRACE_EVENT_INSTANT1( 190 TRACE_EVENT_INSTANT1(
179 "cast_perf_test", "VideoFrameEncoded", 191 "cast_perf_test", "VideoFrameEncoded",
180 TRACE_EVENT_SCOPE_THREAD, 192 TRACE_EVENT_SCOPE_THREAD,
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 if (!last_send_time_.is_null() && last_sent_frame_id_ != -1) { 301 if (!last_send_time_.is_null() && last_sent_frame_id_ != -1) {
290 base::TimeDelta time_since_last_send = 302 base::TimeDelta time_since_last_send =
291 cast_environment_->Clock()->NowTicks() - last_send_time_; 303 cast_environment_->Clock()->NowTicks() - last_send_time_;
292 if (time_since_last_send > rtp_max_delay_) { 304 if (time_since_last_send > rtp_max_delay_) {
293 if (!active_session_) { 305 if (!active_session_) {
294 // We have not received any acks, resend the first encoded frame (id 0), 306 // We have not received any acks, resend the first encoded frame (id 0),
295 // which must also be a key frame. 307 // which must also be a key frame.
296 VLOG(1) << "ACK timeout resend first key frame"; 308 VLOG(1) << "ACK timeout resend first key frame";
297 ResendFrame(0); 309 ResendFrame(0);
298 } else { 310 } else {
299 DCHECK_LE(0, last_acked_frame_id_); 311 if (last_acked_frame_id_ == last_sent_frame_id_) {
300 uint32 frame_id = static_cast<uint32>(last_acked_frame_id_ + 1); 312 // Last frame acked, no point in doing anything
Alpha Left Google 2014/04/29 00:55:05 Please have a test for this case. This is a third
hubbe 2014/04/29 17:19:58 Actually, the problem is that without this if-stat
301 VLOG(1) << "ACK timeout resend frame:" << static_cast<int>(frame_id); 313 } else {
302 ResendFrame(frame_id); 314 DCHECK_LE(0, last_acked_frame_id_);
315 uint32 frame_id = static_cast<uint32>(last_acked_frame_id_ + 1);
316 VLOG(1) << "ACK timeout resend frame:" << static_cast<int>(frame_id);
317 ResendFrame(frame_id);
318 }
303 } 319 }
304 } 320 }
305 } 321 }
306 ScheduleNextResendCheck(); 322 ScheduleNextResendCheck();
307 } 323 }
308 324
309 void VideoSender::ScheduleNextSkippedFramesCheck() { 325 void VideoSender::ScheduleNextSkippedFramesCheck() {
310 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 326 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
311 base::TimeDelta time_to_next; 327 base::TimeDelta time_to_next;
312 if (last_checked_skip_count_time_.is_null()) { 328 if (last_checked_skip_count_time_.is_null()) {
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 if (last_sent_frame_id_ != -1) { 452 if (last_sent_frame_id_ != -1) {
437 DCHECK_LE(0, last_sent_frame_id_); 453 DCHECK_LE(0, last_sent_frame_id_);
438 uint32 frames_in_flight = 0; 454 uint32 frames_in_flight = 0;
439 if (last_acked_frame_id_ != -1) { 455 if (last_acked_frame_id_ != -1) {
440 DCHECK_LE(0, last_acked_frame_id_); 456 DCHECK_LE(0, last_acked_frame_id_);
441 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) - 457 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) -
442 static_cast<uint32>(last_acked_frame_id_); 458 static_cast<uint32>(last_acked_frame_id_);
443 } else { 459 } else {
444 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) + 1; 460 frames_in_flight = static_cast<uint32>(last_sent_frame_id_) + 1;
445 } 461 }
462 frames_in_flight += frames_in_encoder_;
446 VLOG(2) << frames_in_flight 463 VLOG(2) << frames_in_flight
447 << " Frames in flight; last sent: " << last_sent_frame_id_ 464 << " Frames in flight; last sent: " << last_sent_frame_id_
448 << " last acked:" << last_acked_frame_id_; 465 << " last acked:" << last_acked_frame_id_
466 << " frames in encoder: " << frames_in_encoder_;
449 if (frames_in_flight >= max_unacked_frames_) { 467 if (frames_in_flight >= max_unacked_frames_) {
450 video_encoder_->SkipNextFrame(true); 468 video_encoder_->SkipNextFrame(true);
451 return; 469 return;
452 } 470 }
453 DCHECK(frames_in_flight <= max_unacked_frames_); 471 DCHECK(frames_in_flight <= max_unacked_frames_);
454 } 472 }
455 video_encoder_->SkipNextFrame(false); 473 video_encoder_->SkipNextFrame(false);
456 } 474 }
457 475
458 void VideoSender::ResendFrame(uint32 resend_frame_id) { 476 void VideoSender::ResendFrame(uint32 resend_frame_id) {
459 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 477 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
460 MissingFramesAndPacketsMap missing_frames_and_packets; 478 MissingFramesAndPacketsMap missing_frames_and_packets;
461 PacketIdSet missing; 479 PacketIdSet missing;
462 missing_frames_and_packets.insert(std::make_pair(resend_frame_id, missing)); 480 missing_frames_and_packets.insert(std::make_pair(resend_frame_id, missing));
463 last_send_time_ = cast_environment_->Clock()->NowTicks(); 481 last_send_time_ = cast_environment_->Clock()->NowTicks();
464 transport_sender_->ResendPackets(false, missing_frames_and_packets); 482 transport_sender_->ResendPackets(false, missing_frames_and_packets);
465 } 483 }
466 484
467 } // namespace cast 485 } // namespace cast
468 } // namespace media 486 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698