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

Side by Side Diff: media/cast/net/cast_transport_impl.cc

Issue 2048033003: Refactoring: CastTransport InitializeAudio/InitializeVideo. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add comments. Created 4 years, 5 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
« no previous file with comments | « media/cast/net/cast_transport_impl.h ('k') | media/cast/net/cast_transport_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/net/cast_transport_impl.h" 5 #include "media/cast/net/cast_transport_impl.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <algorithm> 8 #include <algorithm>
9 #include <string> 9 #include <string>
10 #include <utility> 10 #include <utility>
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 84
85 private: 85 private:
86 const uint32_t rtp_sender_ssrc_; 86 const uint32_t rtp_sender_ssrc_;
87 const std::unique_ptr<RtcpObserver> rtcp_observer_; 87 const std::unique_ptr<RtcpObserver> rtcp_observer_;
88 const EventMediaType media_type_; 88 const EventMediaType media_type_;
89 CastTransportImpl* const cast_transport_impl_; 89 CastTransportImpl* const cast_transport_impl_;
90 90
91 DISALLOW_COPY_AND_ASSIGN(RtcpClient); 91 DISALLOW_COPY_AND_ASSIGN(RtcpClient);
92 }; 92 };
93 93
94 struct CastTransportImpl::RtpStreamSession {
95 explicit RtpStreamSession(bool is_audio_stream) : is_audio(is_audio_stream) {}
96
97 // Packetizer for audio and video frames.
98 std::unique_ptr<RtpSender> rtp_sender;
99
100 // Maintains RTCP session for audio and video.
101 std::unique_ptr<SenderRtcpSession> rtcp_session;
102
103 // RTCP observer for SenderRtcpSession.
104 std::unique_ptr<RtcpObserver> rtcp_observer;
105
106 // Encrypts data in EncodedFrames before they are sent. Note that it's
107 // important for the encryption to happen here, in code that would execute in
108 // the main browser process, for security reasons. This helps to mitigate
109 // the damage that could be caused by a compromised renderer process.
110 TransportEncryptionHandler encryptor;
111
112 const bool is_audio;
113 };
114
94 CastTransportImpl::CastTransportImpl( 115 CastTransportImpl::CastTransportImpl(
95 base::TickClock* clock, 116 base::TickClock* clock,
96 base::TimeDelta logging_flush_interval, 117 base::TimeDelta logging_flush_interval,
97 std::unique_ptr<Client> client, 118 std::unique_ptr<Client> client,
98 std::unique_ptr<PacketTransport> transport, 119 std::unique_ptr<PacketTransport> transport,
99 const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner) 120 const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner)
100 : clock_(clock), 121 : clock_(clock),
101 logging_flush_interval_(logging_flush_interval), 122 logging_flush_interval_(logging_flush_interval),
102 transport_client_(std::move(client)), 123 transport_client_(std::move(client)),
103 transport_(std::move(transport)), 124 transport_(std::move(transport)),
(...skipping 18 matching lines...) Expand all
122 logging_flush_interval_); 143 logging_flush_interval_);
123 } 144 }
124 transport_->StartReceiving( 145 transport_->StartReceiving(
125 base::Bind(&CastTransportImpl::OnReceivedPacket, base::Unretained(this))); 146 base::Bind(&CastTransportImpl::OnReceivedPacket, base::Unretained(this)));
126 } 147 }
127 148
128 CastTransportImpl::~CastTransportImpl() { 149 CastTransportImpl::~CastTransportImpl() {
129 transport_->StopReceiving(); 150 transport_->StopReceiving();
130 } 151 }
131 152
132 void CastTransportImpl::InitializeAudio( 153 void CastTransportImpl::InitializeStream(
133 const CastTransportRtpConfig& config, 154 const CastTransportRtpConfig& config,
134 std::unique_ptr<RtcpObserver> rtcp_observer) { 155 std::unique_ptr<RtcpObserver> rtcp_observer) {
156 if (sessions_.find(config.ssrc) != sessions_.end())
157 DVLOG(1) << "Initialize an existing stream on RTP sender." << config.ssrc;
158
135 LOG_IF(WARNING, config.aes_key.empty() || config.aes_iv_mask.empty()) 159 LOG_IF(WARNING, config.aes_key.empty() || config.aes_iv_mask.empty())
136 << "Unsafe to send audio with encryption DISABLED."; 160 << "Unsafe to send stream with encryption DISABLED.";
137 if (!audio_encryptor_.Initialize(config.aes_key, config.aes_iv_mask)) { 161
138 transport_client_->OnStatusChanged(TRANSPORT_AUDIO_UNINITIALIZED); 162 bool is_audio = config.rtp_payload_type <= RtpPayloadType::AUDIO_LAST;
163 std::unique_ptr<RtpStreamSession> session(new RtpStreamSession(is_audio));
164
165 if (!session->encryptor.Initialize(config.aes_key, config.aes_iv_mask)) {
166 transport_client_->OnStatusChanged(TRANSPORT_STREAM_UNINITIALIZED);
139 return; 167 return;
140 } 168 }
141 169
142 audio_sender_.reset(new RtpSender(transport_task_runner_, &pacer_)); 170 session->rtp_sender.reset(new RtpSender(transport_task_runner_, &pacer_));
143 if (audio_sender_->Initialize(config)) { 171 if (!session->rtp_sender->Initialize(config)) {
144 // Audio packets have a higher priority. 172 session->rtp_sender.reset();
145 pacer_.RegisterAudioSsrc(config.ssrc); 173 transport_client_->OnStatusChanged(TRANSPORT_STREAM_UNINITIALIZED);
146 pacer_.RegisterPrioritySsrc(config.ssrc);
147 transport_client_->OnStatusChanged(TRANSPORT_AUDIO_INITIALIZED);
148 } else {
149 audio_sender_.reset();
150 transport_client_->OnStatusChanged(TRANSPORT_AUDIO_UNINITIALIZED);
151 return; 174 return;
152 } 175 }
153 176
154 audio_rtcp_observer_.reset( 177 pacer_.RegisterSsrc(config.ssrc, is_audio);
155 new RtcpClient(std::move(rtcp_observer), config.ssrc, AUDIO_EVENT, this)); 178 // Audio packets have a higher priority.
156 audio_rtcp_session_.reset( 179 if (is_audio)
157 new SenderRtcpSession(clock_, &pacer_, audio_rtcp_observer_.get(), 180 pacer_.RegisterPrioritySsrc(config.ssrc);
181
182 session->rtcp_observer.reset(
183 new RtcpClient(std::move(rtcp_observer), config.ssrc,
184 is_audio ? AUDIO_EVENT : VIDEO_EVENT, this));
185 session->rtcp_session.reset(
186 new SenderRtcpSession(clock_, &pacer_, session->rtcp_observer.get(),
158 config.ssrc, config.feedback_ssrc)); 187 config.ssrc, config.feedback_ssrc));
159 pacer_.RegisterAudioSsrc(config.ssrc); 188
160 valid_sender_ssrcs_.insert(config.feedback_ssrc); 189 valid_sender_ssrcs_.insert(config.feedback_ssrc);
161 transport_client_->OnStatusChanged(TRANSPORT_AUDIO_INITIALIZED); 190 sessions_[config.ssrc] = std::move(session);
162 } 191 transport_client_->OnStatusChanged(TRANSPORT_STREAM_INITIALIZED);
163
164 void CastTransportImpl::InitializeVideo(
165 const CastTransportRtpConfig& config,
166 std::unique_ptr<RtcpObserver> rtcp_observer) {
167 LOG_IF(WARNING, config.aes_key.empty() || config.aes_iv_mask.empty())
168 << "Unsafe to send video with encryption DISABLED.";
169 if (!video_encryptor_.Initialize(config.aes_key, config.aes_iv_mask)) {
170 transport_client_->OnStatusChanged(TRANSPORT_VIDEO_UNINITIALIZED);
171 return;
172 }
173
174 video_sender_.reset(new RtpSender(transport_task_runner_, &pacer_));
175 if (!video_sender_->Initialize(config)) {
176 video_sender_.reset();
177 transport_client_->OnStatusChanged(TRANSPORT_VIDEO_UNINITIALIZED);
178 return;
179 }
180
181 video_rtcp_observer_.reset(
182 new RtcpClient(std::move(rtcp_observer), config.ssrc, VIDEO_EVENT, this));
183 video_rtcp_session_.reset(
184 new SenderRtcpSession(clock_, &pacer_, video_rtcp_observer_.get(),
185 config.ssrc, config.feedback_ssrc));
186 pacer_.RegisterVideoSsrc(config.ssrc);
187 valid_sender_ssrcs_.insert(config.feedback_ssrc);
188 transport_client_->OnStatusChanged(TRANSPORT_VIDEO_INITIALIZED);
189 } 192 }
190 193
191 namespace { 194 namespace {
192 void EncryptAndSendFrame(const EncodedFrame& frame, 195 void EncryptAndSendFrame(const EncodedFrame& frame,
193 TransportEncryptionHandler* encryptor, 196 TransportEncryptionHandler* encryptor,
194 RtpSender* sender) { 197 RtpSender* sender) {
195 // TODO(miu): We probably shouldn't attempt to send an empty frame, but this 198 // TODO(miu): We probably shouldn't attempt to send an empty frame, but this
196 // issue is still under investigation. http://crbug.com/519022 199 // issue is still under investigation. http://crbug.com/519022
197 if (encryptor->is_activated() && !frame.data.empty()) { 200 if (encryptor->is_activated() && !frame.data.empty()) {
198 EncodedFrame encrypted_frame; 201 EncodedFrame encrypted_frame;
199 frame.CopyMetadataTo(&encrypted_frame); 202 frame.CopyMetadataTo(&encrypted_frame);
200 if (encryptor->Encrypt(frame.frame_id, frame.data, &encrypted_frame.data)) { 203 if (encryptor->Encrypt(frame.frame_id, frame.data, &encrypted_frame.data)) {
201 sender->SendFrame(encrypted_frame); 204 sender->SendFrame(encrypted_frame);
202 } else { 205 } else {
203 LOG(ERROR) << "Encryption failed. Not sending frame with ID " 206 LOG(ERROR) << "Encryption failed. Not sending frame with ID "
204 << frame.frame_id; 207 << frame.frame_id;
205 } 208 }
206 } else { 209 } else {
207 sender->SendFrame(frame); 210 sender->SendFrame(frame);
208 } 211 }
209 } 212 }
210 } // namespace 213 } // namespace
211 214
212 void CastTransportImpl::InsertFrame(uint32_t ssrc, const EncodedFrame& frame) { 215 void CastTransportImpl::InsertFrame(uint32_t ssrc, const EncodedFrame& frame) {
213 if (audio_sender_ && ssrc == audio_sender_->ssrc()) { 216 auto it = sessions_.find(ssrc);
214 audio_rtcp_session_->WillSendFrame(frame.frame_id); 217 if (it == sessions_.end()) {
215 EncryptAndSendFrame(frame, &audio_encryptor_, audio_sender_.get());
216 } else if (video_sender_ && ssrc == video_sender_->ssrc()) {
217 video_rtcp_session_->WillSendFrame(frame.frame_id);
218 EncryptAndSendFrame(frame, &video_encryptor_, video_sender_.get());
219 } else {
220 NOTREACHED() << "Invalid InsertFrame call."; 218 NOTREACHED() << "Invalid InsertFrame call.";
219 return;
221 } 220 }
221
222 it->second->rtcp_session->WillSendFrame(frame.frame_id);
223 EncryptAndSendFrame(frame, &it->second->encryptor,
224 it->second->rtp_sender.get());
222 } 225 }
223 226
224 void CastTransportImpl::SendSenderReport( 227 void CastTransportImpl::SendSenderReport(
225 uint32_t ssrc, 228 uint32_t ssrc,
226 base::TimeTicks current_time, 229 base::TimeTicks current_time,
227 RtpTimeTicks current_time_as_rtp_timestamp) { 230 RtpTimeTicks current_time_as_rtp_timestamp) {
228 if (audio_sender_ && ssrc == audio_sender_->ssrc()) { 231 auto it = sessions_.find(ssrc);
229 audio_rtcp_session_->SendRtcpReport( 232 if (it == sessions_.end()) {
230 current_time, current_time_as_rtp_timestamp,
231 audio_sender_->send_packet_count(), audio_sender_->send_octet_count());
232 } else if (video_sender_ && ssrc == video_sender_->ssrc()) {
233 video_rtcp_session_->SendRtcpReport(
234 current_time, current_time_as_rtp_timestamp,
235 video_sender_->send_packet_count(), video_sender_->send_octet_count());
236 } else {
237 NOTREACHED() << "Invalid request for sending RTCP packet."; 233 NOTREACHED() << "Invalid request for sending RTCP packet.";
234 return;
238 } 235 }
236
237 it->second->rtcp_session->SendRtcpReport(
238 current_time, current_time_as_rtp_timestamp,
239 it->second->rtp_sender->send_packet_count(),
240 it->second->rtp_sender->send_octet_count());
239 } 241 }
240 242
241 void CastTransportImpl::CancelSendingFrames( 243 void CastTransportImpl::CancelSendingFrames(
242 uint32_t ssrc, 244 uint32_t ssrc,
243 const std::vector<FrameId>& frame_ids) { 245 const std::vector<FrameId>& frame_ids) {
244 if (audio_sender_ && ssrc == audio_sender_->ssrc()) { 246 auto it = sessions_.find(ssrc);
245 audio_sender_->CancelSendingFrames(frame_ids); 247 if (it == sessions_.end()) {
246 } else if (video_sender_ && ssrc == video_sender_->ssrc()) {
247 video_sender_->CancelSendingFrames(frame_ids);
248 } else {
249 NOTREACHED() << "Invalid request for cancel sending."; 248 NOTREACHED() << "Invalid request for cancel sending.";
249 return;
250 } 250 }
251
252 it->second->rtp_sender->CancelSendingFrames(frame_ids);
251 } 253 }
252 254
253 void CastTransportImpl::ResendFrameForKickstart(uint32_t ssrc, 255 void CastTransportImpl::ResendFrameForKickstart(uint32_t ssrc,
254 FrameId frame_id) { 256 FrameId frame_id) {
255 if (audio_sender_ && ssrc == audio_sender_->ssrc()) { 257 auto it = sessions_.find(ssrc);
256 DCHECK(audio_rtcp_session_); 258 if (it == sessions_.end()) {
257 audio_sender_->ResendFrameForKickstart(
258 frame_id, audio_rtcp_session_->current_round_trip_time());
259 } else if (video_sender_ && ssrc == video_sender_->ssrc()) {
260 DCHECK(video_rtcp_session_);
261 video_sender_->ResendFrameForKickstart(
262 frame_id, video_rtcp_session_->current_round_trip_time());
263 } else {
264 NOTREACHED() << "Invalid request for kickstart."; 259 NOTREACHED() << "Invalid request for kickstart.";
260 return;
265 } 261 }
262
263 DCHECK(it->second->rtcp_session);
264 it->second->rtp_sender->ResendFrameForKickstart(
265 frame_id, it->second->rtcp_session->current_round_trip_time());
266 } 266 }
267 267
268 void CastTransportImpl::ResendPackets( 268 void CastTransportImpl::ResendPackets(
269 uint32_t ssrc, 269 uint32_t ssrc,
270 const MissingFramesAndPacketsMap& missing_packets, 270 const MissingFramesAndPacketsMap& missing_packets,
271 bool cancel_rtx_if_not_in_list, 271 bool cancel_rtx_if_not_in_list,
272 const DedupInfo& dedup_info) { 272 const DedupInfo& dedup_info) {
273 if (audio_sender_ && ssrc == audio_sender_->ssrc()) { 273 auto it = sessions_.find(ssrc);
274 audio_sender_->ResendPackets(missing_packets, cancel_rtx_if_not_in_list, 274 if (it == sessions_.end()) {
275 dedup_info);
276 } else if (video_sender_ && ssrc == video_sender_->ssrc()) {
277 video_sender_->ResendPackets(missing_packets, cancel_rtx_if_not_in_list,
278 dedup_info);
279 } else {
280 NOTREACHED() << "Invalid request for retransmission."; 275 NOTREACHED() << "Invalid request for retransmission.";
276 return;
281 } 277 }
278
279 it->second->rtp_sender->ResendPackets(missing_packets,
280 cancel_rtx_if_not_in_list, dedup_info);
282 } 281 }
283 282
284 PacketReceiverCallback CastTransportImpl::PacketReceiverForTesting() { 283 PacketReceiverCallback CastTransportImpl::PacketReceiverForTesting() {
285 return base::Bind(base::IgnoreResult(&CastTransportImpl::OnReceivedPacket), 284 return base::Bind(base::IgnoreResult(&CastTransportImpl::OnReceivedPacket),
286 weak_factory_.GetWeakPtr()); 285 weak_factory_.GetWeakPtr());
287 } 286 }
288 287
289 void CastTransportImpl::SendRawEvents() { 288 void CastTransportImpl::SendRawEvents() {
290 DCHECK(logging_flush_interval_ > base::TimeDelta()); 289 DCHECK(logging_flush_interval_ > base::TimeDelta());
291 290
(...skipping 22 matching lines...) Expand all
314 ssrc = GetSsrcOfSender(data, length); 313 ssrc = GetSsrcOfSender(data, length);
315 } else if (!RtpParser::ParseSsrc(data, length, &ssrc)) { 314 } else if (!RtpParser::ParseSsrc(data, length, &ssrc)) {
316 VLOG(1) << "Invalid RTP packet."; 315 VLOG(1) << "Invalid RTP packet.";
317 return false; 316 return false;
318 } 317 }
319 if (valid_sender_ssrcs_.find(ssrc) == valid_sender_ssrcs_.end()) { 318 if (valid_sender_ssrcs_.find(ssrc) == valid_sender_ssrcs_.end()) {
320 VLOG(1) << "Stale packet received."; 319 VLOG(1) << "Stale packet received.";
321 return false; 320 return false;
322 } 321 }
323 322
324 if (audio_rtcp_session_ && 323 for (const auto& session : sessions_) {
325 audio_rtcp_session_->IncomingRtcpPacket(data, length)) { 324 if (session.second->rtcp_session->IncomingRtcpPacket(data, length))
326 return true; 325 return true;
327 } 326 }
328 if (video_rtcp_session_ && 327
329 video_rtcp_session_->IncomingRtcpPacket(data, length)) {
330 return true;
331 }
332 transport_client_->ProcessRtpPacket(std::move(packet)); 328 transport_client_->ProcessRtpPacket(std::move(packet));
333 return true; 329 return true;
334 } 330 }
335 331
336 void CastTransportImpl::OnReceivedLogMessage( 332 void CastTransportImpl::OnReceivedLogMessage(
337 EventMediaType media_type, 333 EventMediaType media_type,
338 const RtcpReceiverLogMessage& log) { 334 const RtcpReceiverLogMessage& log) {
339 if (logging_flush_interval_ <= base::TimeDelta()) 335 if (logging_flush_interval_ <= base::TimeDelta())
340 return; 336 return;
341 337
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 } 370 }
375 } 371 }
376 } 372 }
377 } 373 }
378 374
379 void CastTransportImpl::OnReceivedCastMessage( 375 void CastTransportImpl::OnReceivedCastMessage(
380 uint32_t ssrc, 376 uint32_t ssrc,
381 const RtcpCastMessage& cast_message) { 377 const RtcpCastMessage& cast_message) {
382 378
383 DedupInfo dedup_info; 379 DedupInfo dedup_info;
384 if (audio_sender_ && audio_sender_->ssrc() == ssrc) { 380 auto it = sessions_.find(ssrc);
385 const int64_t acked_bytes = 381 if (it == sessions_.end() || !it->second->rtp_sender)
386 audio_sender_->GetLastByteSentForFrame(cast_message.ack_frame_id); 382 return;
383
384 if (it->second->is_audio) {
385 const int64_t acked_bytes = it->second->rtp_sender->GetLastByteSentForFrame(
386 cast_message.ack_frame_id);
387 last_byte_acked_for_audio_ = 387 last_byte_acked_for_audio_ =
388 std::max(acked_bytes, last_byte_acked_for_audio_); 388 std::max(acked_bytes, last_byte_acked_for_audio_);
389 } else if (video_sender_ && video_sender_->ssrc() == ssrc) { 389 } else {
390 dedup_info.resend_interval = video_rtcp_session_->current_round_trip_time(); 390 dedup_info.resend_interval =
391 it->second->rtcp_session->current_round_trip_time();
391 392
392 // Only use audio stream to dedup if there is one. 393 // Only use audio stream to dedup if there is one.
393 if (audio_sender_) { 394 if (last_byte_acked_for_audio_) {
394 dedup_info.last_byte_acked_for_audio = last_byte_acked_for_audio_; 395 dedup_info.last_byte_acked_for_audio = last_byte_acked_for_audio_;
395 } 396 }
396 } 397 }
397 398
398 if (!cast_message.missing_frames_and_packets.empty()) { 399 if (!cast_message.missing_frames_and_packets.empty()) {
399 VLOG(2) << "feedback_count: " 400 VLOG(2) << "feedback_count: "
400 << static_cast<uint32_t>(cast_message.feedback_count); 401 << static_cast<uint32_t>(cast_message.feedback_count);
401 // This call does two things. 402 // This call does two things.
402 // 1. Specifies that retransmissions for packets not listed in the set are 403 // 1. Specifies that retransmissions for packets not listed in the set are
403 // cancelled. 404 // cancelled.
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
509 "calling CastTransportImpl::SendRtcpFromRtpReceiver."; 510 "calling CastTransportImpl::SendRtcpFromRtpReceiver.";
510 return; 511 return;
511 } 512 }
512 pacer_.SendRtcpPacket(rtcp_builder_at_rtp_receiver_->local_ssrc(), 513 pacer_.SendRtcpPacket(rtcp_builder_at_rtp_receiver_->local_ssrc(),
513 rtcp_builder_at_rtp_receiver_->Finish()); 514 rtcp_builder_at_rtp_receiver_->Finish());
514 rtcp_builder_at_rtp_receiver_.reset(); 515 rtcp_builder_at_rtp_receiver_.reset();
515 } 516 }
516 517
517 } // namespace cast 518 } // namespace cast
518 } // namespace media 519 } // namespace media
OLDNEW
« no previous file with comments | « media/cast/net/cast_transport_impl.h ('k') | media/cast/net/cast_transport_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698