OLD | NEW |
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 "chrome/renderer/media/cast_rtp_stream.h" | 5 #include "chrome/renderer/media/cast_rtp_stream.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/weak_ptr.h" | 10 #include "base/memory/weak_ptr.h" |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 params.payload.min_latency_ms ? | 207 params.payload.min_latency_ms ? |
208 params.payload.min_latency_ms : | 208 params.payload.min_latency_ms : |
209 params.payload.max_latency_ms); | 209 params.payload.max_latency_ms); |
210 config->max_playout_delay = | 210 config->max_playout_delay = |
211 base::TimeDelta::FromMilliseconds(params.payload.max_latency_ms); | 211 base::TimeDelta::FromMilliseconds(params.payload.max_latency_ms); |
212 if (config->min_playout_delay <= base::TimeDelta()) | 212 if (config->min_playout_delay <= base::TimeDelta()) |
213 return false; | 213 return false; |
214 if (config->min_playout_delay > config->max_playout_delay) | 214 if (config->min_playout_delay > config->max_playout_delay) |
215 return false; | 215 return false; |
216 config->rtp_payload_type = params.payload.payload_type; | 216 config->rtp_payload_type = params.payload.payload_type; |
217 config->width = params.payload.width; | |
218 config->height = params.payload.height; | |
219 if (config->width < 2 || config->height < 2) | |
220 return false; | |
221 config->min_bitrate = config->start_bitrate = | 217 config->min_bitrate = config->start_bitrate = |
222 params.payload.min_bitrate * kBitrateMultiplier; | 218 params.payload.min_bitrate * kBitrateMultiplier; |
223 config->max_bitrate = params.payload.max_bitrate * kBitrateMultiplier; | 219 config->max_bitrate = params.payload.max_bitrate * kBitrateMultiplier; |
224 if (config->min_bitrate > config->max_bitrate) | 220 if (config->min_bitrate > config->max_bitrate) |
225 return false; | 221 return false; |
226 config->start_bitrate = config->min_bitrate; | 222 config->start_bitrate = config->min_bitrate; |
227 config->max_frame_rate = static_cast<int>( | 223 config->max_frame_rate = static_cast<int>( |
228 std::max(1.0, params.payload.max_frame_rate) + 0.5); | 224 std::max(1.0, params.payload.max_frame_rate) + 0.5); |
229 if (config->max_frame_rate > 120) | 225 if (config->max_frame_rate > 120) |
230 return false; | 226 return false; |
(...skipping 19 matching lines...) Expand all Loading... |
250 // This class receives MediaStreamTrack events and video frames from a | 246 // This class receives MediaStreamTrack events and video frames from a |
251 // MediaStreamTrack. | 247 // MediaStreamTrack. |
252 // | 248 // |
253 // Threading: Video frames are received on the IO thread and then | 249 // Threading: Video frames are received on the IO thread and then |
254 // forwarded to media::cast::VideoFrameInput through a static method. | 250 // forwarded to media::cast::VideoFrameInput through a static method. |
255 // Member variables of this class are only accessed on the render thread. | 251 // Member variables of this class are only accessed on the render thread. |
256 class CastVideoSink : public base::SupportsWeakPtr<CastVideoSink>, | 252 class CastVideoSink : public base::SupportsWeakPtr<CastVideoSink>, |
257 public content::MediaStreamVideoSink { | 253 public content::MediaStreamVideoSink { |
258 public: | 254 public: |
259 // |track| provides data for this sink. | 255 // |track| provides data for this sink. |
260 // |expected_natural_size| is the expected dimension of the video frame. | |
261 // |error_callback| is called if video formats don't match. | 256 // |error_callback| is called if video formats don't match. |
262 CastVideoSink(const blink::WebMediaStreamTrack& track, | 257 CastVideoSink(const blink::WebMediaStreamTrack& track, |
263 const gfx::Size& expected_natural_size, | |
264 const CastRtpStream::ErrorCallback& error_callback) | 258 const CastRtpStream::ErrorCallback& error_callback) |
265 : track_(track), | 259 : track_(track), |
266 sink_added_(false), | 260 sink_added_(false), |
267 expected_natural_size_(expected_natural_size), | |
268 error_callback_(error_callback) {} | 261 error_callback_(error_callback) {} |
269 | 262 |
270 ~CastVideoSink() override { | 263 ~CastVideoSink() override { |
271 if (sink_added_) | 264 if (sink_added_) |
272 RemoveFromVideoTrack(this, track_); | 265 RemoveFromVideoTrack(this, track_); |
273 } | 266 } |
274 | 267 |
275 // This static method is used to forward video frames to |frame_input|. | 268 // This static method is used to forward video frames to |frame_input|. |
276 static void OnVideoFrame( | 269 static void OnVideoFrame( |
277 // These parameters are already bound when callback is created. | 270 // These parameters are already bound when callback is created. |
278 const gfx::Size& expected_natural_size, | |
279 const CastRtpStream::ErrorCallback& error_callback, | 271 const CastRtpStream::ErrorCallback& error_callback, |
280 const scoped_refptr<media::cast::VideoFrameInput> frame_input, | 272 const scoped_refptr<media::cast::VideoFrameInput> frame_input, |
281 // These parameters are passed for each frame. | 273 // These parameters are passed for each frame. |
282 const scoped_refptr<media::VideoFrame>& frame, | 274 const scoped_refptr<media::VideoFrame>& frame, |
283 const media::VideoCaptureFormat& format, | 275 const media::VideoCaptureFormat& format, |
284 const base::TimeTicks& estimated_capture_time) { | 276 const base::TimeTicks& estimated_capture_time) { |
285 if (frame->natural_size() != expected_natural_size) { | |
286 error_callback.Run( | |
287 base::StringPrintf("Video frame resolution does not match config." | |
288 " Expected %dx%d. Got %dx%d.", | |
289 expected_natural_size.width(), | |
290 expected_natural_size.height(), | |
291 frame->natural_size().width(), | |
292 frame->natural_size().height())); | |
293 return; | |
294 } | |
295 | |
296 base::TimeTicks timestamp; | 277 base::TimeTicks timestamp; |
297 if (estimated_capture_time.is_null()) | 278 if (estimated_capture_time.is_null()) |
298 timestamp = base::TimeTicks::Now(); | 279 timestamp = base::TimeTicks::Now(); |
299 else | 280 else |
300 timestamp = estimated_capture_time; | 281 timestamp = estimated_capture_time; |
301 | 282 |
302 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 283 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
303 TRACE_EVENT_INSTANT2( | 284 TRACE_EVENT_INSTANT2( |
304 "cast_perf_test", "MediaStreamVideoSink::OnVideoFrame", | 285 "cast_perf_test", "MediaStreamVideoSink::OnVideoFrame", |
305 TRACE_EVENT_SCOPE_THREAD, | 286 TRACE_EVENT_SCOPE_THREAD, |
306 "timestamp", timestamp.ToInternalValue(), | 287 "timestamp", timestamp.ToInternalValue(), |
307 "time_delta", frame->timestamp().ToInternalValue()); | 288 "time_delta", frame->timestamp().ToInternalValue()); |
308 frame_input->InsertRawVideoFrame(frame, timestamp); | 289 frame_input->InsertRawVideoFrame(frame, timestamp); |
309 } | 290 } |
310 | 291 |
311 // Attach this sink to a video track represented by |track_|. | 292 // Attach this sink to a video track represented by |track_|. |
312 // Data received from the track will be submitted to |frame_input|. | 293 // Data received from the track will be submitted to |frame_input|. |
313 void AddToTrack( | 294 void AddToTrack( |
314 const scoped_refptr<media::cast::VideoFrameInput>& frame_input) { | 295 const scoped_refptr<media::cast::VideoFrameInput>& frame_input) { |
315 DCHECK(!sink_added_); | 296 DCHECK(!sink_added_); |
316 sink_added_ = true; | 297 sink_added_ = true; |
317 AddToVideoTrack( | 298 AddToVideoTrack( |
318 this, | 299 this, |
319 base::Bind( | 300 base::Bind( |
320 &CastVideoSink::OnVideoFrame, | 301 &CastVideoSink::OnVideoFrame, |
321 expected_natural_size_, | |
322 error_callback_, | 302 error_callback_, |
323 frame_input), | 303 frame_input), |
324 track_); | 304 track_); |
325 } | 305 } |
326 | 306 |
327 private: | 307 private: |
328 blink::WebMediaStreamTrack track_; | 308 blink::WebMediaStreamTrack track_; |
329 bool sink_added_; | 309 bool sink_added_; |
330 gfx::Size expected_natural_size_; | |
331 CastRtpStream::ErrorCallback error_callback_; | 310 CastRtpStream::ErrorCallback error_callback_; |
332 | 311 |
333 DISALLOW_COPY_AND_ASSIGN(CastVideoSink); | 312 DISALLOW_COPY_AND_ASSIGN(CastVideoSink); |
334 }; | 313 }; |
335 | 314 |
336 // Receives audio data from a MediaStreamTrack. Data is submitted to | 315 // Receives audio data from a MediaStreamTrack. Data is submitted to |
337 // media::cast::FrameInput. | 316 // media::cast::FrameInput. |
338 // | 317 // |
339 // Threading: Audio frames are received on the real-time audio thread. | 318 // Threading: Audio frames are received on the real-time audio thread. |
340 // Note that RemoveFromAudioTrack() is synchronous and we have | 319 // Note that RemoveFromAudioTrack() is synchronous and we have |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 start_callback.Run(); | 515 start_callback.Run(); |
537 } else { | 516 } else { |
538 VideoSenderConfig config; | 517 VideoSenderConfig config; |
539 if (!ToVideoSenderConfig(params, &config)) { | 518 if (!ToVideoSenderConfig(params, &config)) { |
540 DidEncounterError("Invalid parameters for video."); | 519 DidEncounterError("Invalid parameters for video."); |
541 return; | 520 return; |
542 } | 521 } |
543 // See the code for audio above for explanation of callbacks. | 522 // See the code for audio above for explanation of callbacks. |
544 video_sink_.reset(new CastVideoSink( | 523 video_sink_.reset(new CastVideoSink( |
545 track_, | 524 track_, |
546 gfx::Size(config.width, config.height), | |
547 media::BindToCurrentLoop(base::Bind(&CastRtpStream::DidEncounterError, | 525 media::BindToCurrentLoop(base::Bind(&CastRtpStream::DidEncounterError, |
548 weak_factory_.GetWeakPtr())))); | 526 weak_factory_.GetWeakPtr())))); |
549 cast_session_->StartVideo( | 527 cast_session_->StartVideo( |
550 config, | 528 config, |
551 base::Bind(&CastVideoSink::AddToTrack, video_sink_->AsWeakPtr()), | 529 base::Bind(&CastVideoSink::AddToTrack, video_sink_->AsWeakPtr()), |
552 base::Bind(&CastRtpStream::DidEncounterError, | 530 base::Bind(&CastRtpStream::DidEncounterError, |
553 weak_factory_.GetWeakPtr())); | 531 weak_factory_.GetWeakPtr())); |
554 start_callback.Run(); | 532 start_callback.Run(); |
555 } | 533 } |
556 } | 534 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
591 void CastRtpStream::DidEncounterError(const std::string& message) { | 569 void CastRtpStream::DidEncounterError(const std::string& message) { |
592 DVLOG(1) << "CastRtpStream::DidEncounterError(" << message << ") = " | 570 DVLOG(1) << "CastRtpStream::DidEncounterError(" << message << ") = " |
593 << (IsAudio() ? "audio" : "video"); | 571 << (IsAudio() ? "audio" : "video"); |
594 // Save the WeakPtr first because the error callback might delete this object. | 572 // Save the WeakPtr first because the error callback might delete this object. |
595 base::WeakPtr<CastRtpStream> ptr = weak_factory_.GetWeakPtr(); | 573 base::WeakPtr<CastRtpStream> ptr = weak_factory_.GetWeakPtr(); |
596 error_callback_.Run(message); | 574 error_callback_.Run(message); |
597 content::RenderThread::Get()->GetTaskRunner()->PostTask( | 575 content::RenderThread::Get()->GetTaskRunner()->PostTask( |
598 FROM_HERE, | 576 FROM_HERE, |
599 base::Bind(&CastRtpStream::Stop, ptr)); | 577 base::Bind(&CastRtpStream::Stop, ptr)); |
600 } | 578 } |
OLD | NEW |