Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/sender/video_sender.h" | 5 #include "media/cast/sender/video_sender.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cstring> | 8 #include <cstring> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/debug/trace_event.h" | 11 #include "base/debug/trace_event.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
| 14 #include "media/cast/cast_defines.h" | 14 #include "media/cast/cast_defines.h" |
| 15 #include "media/cast/net/cast_transport_config.h" | 15 #include "media/cast/net/cast_transport_config.h" |
| 16 #include "media/cast/sender/external_video_encoder.h" | 16 #include "media/cast/sender/external_video_encoder.h" |
| 17 #include "media/cast/sender/video_encoder_impl.h" | 17 #include "media/cast/sender/video_encoder_impl.h" |
| 18 | 18 |
| 19 namespace media { | 19 namespace media { |
| 20 namespace cast { | 20 namespace cast { |
| 21 | 21 |
| 22 const int kRoundTripsNeeded = 4; | |
| 23 | |
| 22 // Note, we use a fixed bitrate value when external video encoder is used. | 24 // Note, we use a fixed bitrate value when external video encoder is used. |
| 23 // Some hardware encoder shows bad behavior if we set the bitrate too | 25 // Some hardware encoder shows bad behavior if we set the bitrate too |
| 24 // frequently, e.g. quality drop, not abiding by target bitrate, etc. | 26 // frequently, e.g. quality drop, not abiding by target bitrate, etc. |
| 25 // See details: crbug.com/392086. | 27 // See details: crbug.com/392086. |
| 26 VideoSender::VideoSender( | 28 VideoSender::VideoSender( |
| 27 scoped_refptr<CastEnvironment> cast_environment, | 29 scoped_refptr<CastEnvironment> cast_environment, |
| 28 const VideoSenderConfig& video_config, | 30 const VideoSenderConfig& video_config, |
| 29 const CastInitializationCallback& initialization_cb, | 31 const CastInitializationCallback& initialization_cb, |
| 30 const CreateVideoEncodeAcceleratorCallback& create_vea_cb, | 32 const CreateVideoEncodeAcceleratorCallback& create_vea_cb, |
| 31 const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb, | 33 const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb, |
| 32 CastTransportSender* const transport_sender) | 34 CastTransportSender* const transport_sender, |
| 35 const PlayoutDelayChangeCB& playout_delay_change_cb) | |
| 33 : FrameSender( | 36 : FrameSender( |
| 34 cast_environment, | 37 cast_environment, |
| 35 false, | 38 false, |
| 36 transport_sender, | 39 transport_sender, |
| 37 base::TimeDelta::FromMilliseconds(video_config.rtcp_interval), | 40 base::TimeDelta::FromMilliseconds(video_config.rtcp_interval), |
| 38 kVideoFrequency, | 41 kVideoFrequency, |
| 39 video_config.ssrc, | 42 video_config.ssrc, |
| 40 video_config.max_frame_rate, | 43 video_config.max_frame_rate, |
| 41 video_config.target_playout_delay, | 44 video_config.min_playout_delay, |
| 45 video_config.max_playout_delay, | |
| 42 NewFixedCongestionControl( | 46 NewFixedCongestionControl( |
| 43 (video_config.min_bitrate + video_config.max_bitrate) / 2)), | 47 (video_config.min_bitrate + video_config.max_bitrate) / 2)), |
| 44 frames_in_encoder_(0), | 48 frames_in_encoder_(0), |
| 45 last_bitrate_(0), | 49 last_bitrate_(0), |
| 50 playout_delay_change_cb_(playout_delay_change_cb), | |
| 46 weak_factory_(this) { | 51 weak_factory_(this) { |
| 47 cast_initialization_status_ = STATUS_VIDEO_UNINITIALIZED; | 52 cast_initialization_status_ = STATUS_VIDEO_UNINITIALIZED; |
| 48 VLOG(1) << "max_unacked_frames is " << max_unacked_frames_ | 53 VLOG(1) << "max_unacked_frames is " << max_unacked_frames_ |
| 49 << " for target_playout_delay=" | 54 << " for target_playout_delay=" |
| 50 << target_playout_delay_.InMilliseconds() << " ms" | 55 << target_playout_delay_.InMilliseconds() << " ms" |
| 51 << " and max_frame_rate=" << video_config.max_frame_rate; | 56 << " and max_frame_rate=" << video_config.max_frame_rate; |
| 52 DCHECK_GT(max_unacked_frames_, 0); | 57 DCHECK_GT(max_unacked_frames_, 0); |
| 53 | 58 |
| 54 if (video_config.use_external_encoder) { | 59 if (video_config.use_external_encoder) { |
| 55 video_encoder_.reset(new ExternalVideoEncoder( | 60 video_encoder_.reset(new ExternalVideoEncoder( |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 75 cast_environment->PostTask( | 80 cast_environment->PostTask( |
| 76 CastEnvironment::MAIN, | 81 CastEnvironment::MAIN, |
| 77 FROM_HERE, | 82 FROM_HERE, |
| 78 base::Bind(initialization_cb, cast_initialization_status_)); | 83 base::Bind(initialization_cb, cast_initialization_status_)); |
| 79 } | 84 } |
| 80 | 85 |
| 81 media::cast::CastTransportRtpConfig transport_config; | 86 media::cast::CastTransportRtpConfig transport_config; |
| 82 transport_config.ssrc = video_config.ssrc; | 87 transport_config.ssrc = video_config.ssrc; |
| 83 transport_config.feedback_ssrc = video_config.incoming_feedback_ssrc; | 88 transport_config.feedback_ssrc = video_config.incoming_feedback_ssrc; |
| 84 transport_config.rtp_payload_type = video_config.rtp_payload_type; | 89 transport_config.rtp_payload_type = video_config.rtp_payload_type; |
| 85 transport_config.stored_frames = max_unacked_frames_; | 90 transport_config.stored_frames = |
| 91 std::min(kMaxUnackedFrames, | |
| 92 1 + static_cast<int>(max_playout_delay_ * | |
| 93 max_frame_rate_ / | |
| 94 base::TimeDelta::FromSeconds(1))); | |
| 86 transport_config.aes_key = video_config.aes_key; | 95 transport_config.aes_key = video_config.aes_key; |
| 87 transport_config.aes_iv_mask = video_config.aes_iv_mask; | 96 transport_config.aes_iv_mask = video_config.aes_iv_mask; |
| 88 | 97 |
| 89 transport_sender->InitializeVideo( | 98 transport_sender->InitializeVideo( |
| 90 transport_config, | 99 transport_config, |
| 91 base::Bind(&VideoSender::OnReceivedCastFeedback, | 100 base::Bind(&VideoSender::OnReceivedCastFeedback, |
| 92 weak_factory_.GetWeakPtr()), | 101 weak_factory_.GetWeakPtr()), |
| 93 base::Bind(&VideoSender::OnMeasuredRoundTripTime, | 102 base::Bind(&VideoSender::OnMeasuredRoundTripTime, |
| 94 weak_factory_.GetWeakPtr())); | 103 weak_factory_.GetWeakPtr())); |
| 95 } | 104 } |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 118 kFrameIdUnknown); | 127 kFrameIdUnknown); |
| 119 | 128 |
| 120 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 129 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
| 121 TRACE_EVENT_INSTANT2( | 130 TRACE_EVENT_INSTANT2( |
| 122 "cast_perf_test", "InsertRawVideoFrame", | 131 "cast_perf_test", "InsertRawVideoFrame", |
| 123 TRACE_EVENT_SCOPE_THREAD, | 132 TRACE_EVENT_SCOPE_THREAD, |
| 124 "timestamp", capture_time.ToInternalValue(), | 133 "timestamp", capture_time.ToInternalValue(), |
| 125 "rtp_timestamp", rtp_timestamp); | 134 "rtp_timestamp", rtp_timestamp); |
| 126 | 135 |
| 127 if (ShouldDropNextFrame(capture_time)) { | 136 if (ShouldDropNextFrame(capture_time)) { |
| 137 base::TimeDelta new_target_delay = std::min( | |
| 138 current_round_trip_time_ * kRoundTripsNeeded, | |
|
Alpha Left Google
2014/09/11 01:24:26
Have you considered applying a low pass filter? Or
hubbe
2014/09/11 19:17:19
My original upload used a sliding window of RTT re
| |
| 139 max_playout_delay_); | |
| 140 if (new_target_delay > target_playout_delay_) { | |
| 141 playout_delay_change_cb_.Run(new_target_delay); | |
| 142 } | |
| 128 VLOG(1) << "Dropping frame due to too many frames currently in-flight."; | 143 VLOG(1) << "Dropping frame due to too many frames currently in-flight."; |
| 129 return; | 144 return; |
| 130 } | 145 } |
| 131 | 146 |
| 132 uint32 bitrate = congestion_control_->GetBitrate( | 147 uint32 bitrate = congestion_control_->GetBitrate( |
| 133 capture_time + target_playout_delay_, target_playout_delay_); | 148 capture_time + target_playout_delay_, target_playout_delay_); |
| 134 if (bitrate != last_bitrate_) { | 149 if (bitrate != last_bitrate_) { |
| 135 video_encoder_->SetBitRate(bitrate); | 150 video_encoder_->SetBitRate(bitrate); |
| 136 last_bitrate_ = bitrate; | 151 last_bitrate_ = bitrate; |
| 137 } | 152 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 169 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 184 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 170 | 185 |
| 171 frames_in_encoder_--; | 186 frames_in_encoder_--; |
| 172 DCHECK_GE(frames_in_encoder_, 0); | 187 DCHECK_GE(frames_in_encoder_, 0); |
| 173 | 188 |
| 174 SendEncodedFrame(encoder_bitrate, encoded_frame.Pass()); | 189 SendEncodedFrame(encoder_bitrate, encoded_frame.Pass()); |
| 175 } | 190 } |
| 176 | 191 |
| 177 } // namespace cast | 192 } // namespace cast |
| 178 } // namespace media | 193 } // namespace media |
| OLD | NEW |