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/debug/trace_event.h" | 8 #include "base/debug/trace_event.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 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
193 } | 193 } |
194 if (!config->use_external_encoder) { | 194 if (!config->use_external_encoder) { |
195 config->number_of_encode_threads = NumberOfEncodeThreads(); | 195 config->number_of_encode_threads = NumberOfEncodeThreads(); |
196 } | 196 } |
197 return true; | 197 return true; |
198 } | 198 } |
199 | 199 |
200 } // namespace | 200 } // namespace |
201 | 201 |
202 // This class receives MediaStreamTrack events and video frames from a | 202 // This class receives MediaStreamTrack events and video frames from a |
203 // MediaStreamTrack. Video frames are submitted to media::cast::FrameInput. | 203 // MediaStreamTrack. |
204 // | 204 // |
205 // Threading: Video frames are received on the render thread. | 205 // Threading: Video frames are received on the IO thread and then |
206 // forwarded to media::cast::VideoFrameInput through a static method. | |
207 // Member variables of this class are only accessed on the render thread. | |
206 class CastVideoSink : public base::SupportsWeakPtr<CastVideoSink>, | 208 class CastVideoSink : public base::SupportsWeakPtr<CastVideoSink>, |
207 public content::MediaStreamVideoSink { | 209 public content::MediaStreamVideoSink { |
208 public: | 210 public: |
209 // |track| provides data for this sink. | 211 // |track| provides data for this sink. |
210 // |expected_coded_size| is the expected dimension of the video frame. | 212 // |expected_coded_size| is the expected dimension of the video frame. |
211 // |error_callback| is called if video formats don't match. | 213 // |error_callback| is called if video formats don't match. |
212 CastVideoSink(const blink::WebMediaStreamTrack& track, | 214 CastVideoSink(const blink::WebMediaStreamTrack& track, |
213 const gfx::Size& expected_coded_size, | 215 const gfx::Size& expected_coded_size, |
214 const CastRtpStream::ErrorCallback& error_callback) | 216 const CastRtpStream::ErrorCallback& error_callback) |
215 : track_(track), | 217 : track_(track), |
216 sink_added_(false), | 218 sink_added_(false), |
217 expected_coded_size_(expected_coded_size), | 219 expected_coded_size_(expected_coded_size), |
218 error_callback_(error_callback) {} | 220 error_callback_(error_callback) {} |
219 | 221 |
220 virtual ~CastVideoSink() { | 222 virtual ~CastVideoSink() { |
221 if (sink_added_) | 223 if (sink_added_) |
222 RemoveFromVideoTrack(this, track_); | 224 RemoveFromVideoTrack(this, track_); |
223 } | 225 } |
224 | 226 |
225 // content::MediaStreamVideoSink implementation. | 227 // This static method is used to forward video frames to |frame_input|. |
226 virtual void OnVideoFrame(const scoped_refptr<media::VideoFrame>& frame) | 228 static void OnVideoFrame( |
227 OVERRIDE { | 229 // These parameters are already bound when callback is created. |
228 if (frame->coded_size() != expected_coded_size_) { | 230 const gfx::Size& expected_coded_size, |
229 error_callback_.Run("Video frame resolution does not match config."); | 231 const CastRtpStream::ErrorCallback& error_callback, |
232 const scoped_refptr<media::cast::VideoFrameInput> frame_input, | |
233 // These parameters are passed for each frame. | |
234 const scoped_refptr<media::VideoFrame>& frame, | |
235 const media::VideoCaptureFormat& format) { | |
236 if (frame->coded_size() != expected_coded_size) { | |
perkj_chrome
2014/05/08 08:15:08
FYI- coded_size() is the size from the source befo
Alpha Left Google
2014/05/08 18:45:51
I see. I think this is good for now. We're not app
| |
237 error_callback.Run("Video frame resolution does not match config."); | |
230 return; | 238 return; |
231 } | 239 } |
232 | 240 |
233 // Capture time is calculated using the time when the first frame | 241 const base::TimeTicks now = base::TimeTicks::Now(); |
234 // is delivered. Doing so has less jitter because each frame has | |
235 // a TimeDelta from the first frame. However there is a delay between | |
236 // capture and delivery here for the first frame. We do not account | |
237 // for this delay. | |
238 if (first_frame_timestamp_.is_null()) | |
239 first_frame_timestamp_ = base::TimeTicks::Now() - frame->timestamp(); | |
240 | 242 |
241 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 243 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
242 TRACE_EVENT_INSTANT2( | 244 TRACE_EVENT_INSTANT2( |
243 "mirroring", "MediaStreamVideoSink::OnVideoFrame", | 245 "cast_perf_test", "MediaStreamVideoSink::OnVideoFrame", |
244 TRACE_EVENT_SCOPE_THREAD, | 246 TRACE_EVENT_SCOPE_THREAD, |
245 "timestamp", | 247 "timestamp", now.ToInternalValue(), |
246 (first_frame_timestamp_ + frame->timestamp()).ToInternalValue(), | |
247 "time_delta", frame->timestamp().ToInternalValue()); | 248 "time_delta", frame->timestamp().ToInternalValue()); |
248 | 249 frame_input->InsertRawVideoFrame(frame, now); |
249 frame_input_->InsertRawVideoFrame( | |
250 frame, first_frame_timestamp_ + frame->timestamp()); | |
251 } | 250 } |
252 | 251 |
253 // Attach this sink to a video track represented by |track_|. | 252 // Attach this sink to a video track represented by |track_|. |
254 // Data received from the track will be submitted to |frame_input|. | 253 // Data received from the track will be submitted to |frame_input|. |
255 void AddToTrack( | 254 void AddToTrack( |
256 const scoped_refptr<media::cast::VideoFrameInput>& frame_input) { | 255 const scoped_refptr<media::cast::VideoFrameInput>& frame_input) { |
257 DCHECK(!sink_added_); | 256 DCHECK(!sink_added_); |
258 sink_added_ = true; | 257 sink_added_ = true; |
259 | 258 AddToVideoTrack( |
260 frame_input_ = frame_input; | 259 this, |
261 AddToVideoTrack(this, track_); | 260 base::Bind( |
261 &CastVideoSink::OnVideoFrame, | |
262 expected_coded_size_, | |
263 error_callback_, | |
264 frame_input), | |
265 track_); | |
262 } | 266 } |
263 | 267 |
264 private: | 268 private: |
265 blink::WebMediaStreamTrack track_; | 269 blink::WebMediaStreamTrack track_; |
266 scoped_refptr<media::cast::VideoFrameInput> frame_input_; | |
267 bool sink_added_; | 270 bool sink_added_; |
268 gfx::Size expected_coded_size_; | 271 gfx::Size expected_coded_size_; |
269 CastRtpStream::ErrorCallback error_callback_; | 272 CastRtpStream::ErrorCallback error_callback_; |
270 base::TimeTicks first_frame_timestamp_; | |
271 | 273 |
272 DISALLOW_COPY_AND_ASSIGN(CastVideoSink); | 274 DISALLOW_COPY_AND_ASSIGN(CastVideoSink); |
273 }; | 275 }; |
274 | 276 |
275 // Receives audio data from a MediaStreamTrack. Data is submitted to | 277 // Receives audio data from a MediaStreamTrack. Data is submitted to |
276 // media::cast::FrameInput. | 278 // media::cast::FrameInput. |
277 // | 279 // |
278 // Threading: Audio frames are received on the real-time audio thread. | 280 // Threading: Audio frames are received on the real-time audio thread. |
281 // Note that RemoveFromAudioTrack() is synchronous and we have | |
282 // gurantee that there will be no more audio data after calling it. | |
279 class CastAudioSink : public base::SupportsWeakPtr<CastAudioSink>, | 283 class CastAudioSink : public base::SupportsWeakPtr<CastAudioSink>, |
280 public content::MediaStreamAudioSink { | 284 public content::MediaStreamAudioSink { |
281 public: | 285 public: |
282 // |track| provides data for this sink. | 286 // |track| provides data for this sink. |
283 // |error_callback| is called if audio formats don't match. | 287 // |error_callback| is called if audio formats don't match. |
284 CastAudioSink(const blink::WebMediaStreamTrack& track, | 288 CastAudioSink(const blink::WebMediaStreamTrack& track, |
285 const CastRtpStream::ErrorCallback& error_callback, | 289 const CastRtpStream::ErrorCallback& error_callback, |
286 int output_channels, | 290 int output_channels, |
287 int output_sample_rate) | 291 int output_sample_rate) |
288 : track_(track), | 292 : track_(track), |
289 sink_added_(false), | 293 sink_added_(false), |
290 error_callback_(error_callback), | 294 error_callback_(error_callback), |
291 weak_factory_(this), | 295 weak_factory_(this), |
292 input_preroll_(0), | |
293 output_channels_(output_channels), | 296 output_channels_(output_channels), |
294 output_sample_rate_(output_sample_rate) {} | 297 output_sample_rate_(output_sample_rate), |
298 input_preroll_(0) {} | |
295 | 299 |
296 virtual ~CastAudioSink() { | 300 virtual ~CastAudioSink() { |
297 if (sink_added_) | 301 if (sink_added_) |
298 RemoveFromAudioTrack(this, track_); | 302 RemoveFromAudioTrack(this, track_); |
299 } | 303 } |
300 | 304 |
301 // Called on real-time audio thread. | 305 // Called on real-time audio thread. |
302 // content::MediaStreamAudioSink implementation. | 306 // content::MediaStreamAudioSink implementation. |
303 virtual void OnData(const int16* audio_data, | 307 virtual void OnData(const int16* audio_data, |
304 int sample_rate, | 308 int sample_rate, |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
392 void ProvideData(int frame_delay, media::AudioBus* output_bus) { | 396 void ProvideData(int frame_delay, media::AudioBus* output_bus) { |
393 fifo_->Consume(output_bus, 0, output_bus->frames()); | 397 fifo_->Consume(output_bus, 0, output_bus->frames()); |
394 } | 398 } |
395 | 399 |
396 private: | 400 private: |
397 blink::WebMediaStreamTrack track_; | 401 blink::WebMediaStreamTrack track_; |
398 bool sink_added_; | 402 bool sink_added_; |
399 CastRtpStream::ErrorCallback error_callback_; | 403 CastRtpStream::ErrorCallback error_callback_; |
400 base::WeakPtrFactory<CastAudioSink> weak_factory_; | 404 base::WeakPtrFactory<CastAudioSink> weak_factory_; |
401 | 405 |
406 const int output_channels_; | |
407 const int output_sample_rate_; | |
408 | |
409 // These member are accessed on the real-time audio time only. | |
410 scoped_refptr<media::cast::AudioFrameInput> frame_input_; | |
402 scoped_ptr<media::MultiChannelResampler> resampler_; | 411 scoped_ptr<media::MultiChannelResampler> resampler_; |
403 scoped_ptr<media::AudioFifo> fifo_; | 412 scoped_ptr<media::AudioFifo> fifo_; |
404 scoped_ptr<media::AudioBus> fifo_input_bus_; | 413 scoped_ptr<media::AudioBus> fifo_input_bus_; |
405 int input_preroll_; | 414 int input_preroll_; |
406 const int output_channels_; | |
407 const int output_sample_rate_; | |
408 | |
409 // This member is accessed on the real-time audio time. | |
410 scoped_refptr<media::cast::AudioFrameInput> frame_input_; | |
411 | 415 |
412 DISALLOW_COPY_AND_ASSIGN(CastAudioSink); | 416 DISALLOW_COPY_AND_ASSIGN(CastAudioSink); |
413 }; | 417 }; |
414 | 418 |
415 CastRtpParams::CastRtpParams(const CastRtpPayloadParams& payload_params) | 419 CastRtpParams::CastRtpParams(const CastRtpPayloadParams& payload_params) |
416 : payload(payload_params) {} | 420 : payload(payload_params) {} |
417 | 421 |
418 CastCodecSpecificParams::CastCodecSpecificParams() {} | 422 CastCodecSpecificParams::CastCodecSpecificParams() {} |
419 | 423 |
420 CastCodecSpecificParams::~CastCodecSpecificParams() {} | 424 CastCodecSpecificParams::~CastCodecSpecificParams() {} |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
528 } | 532 } |
529 | 533 |
530 void CastRtpStream::DidEncounterError(const std::string& message) { | 534 void CastRtpStream::DidEncounterError(const std::string& message) { |
531 // Save the WeakPtr first because the error callback might delete this object. | 535 // Save the WeakPtr first because the error callback might delete this object. |
532 base::WeakPtr<CastRtpStream> ptr = weak_factory_.GetWeakPtr(); | 536 base::WeakPtr<CastRtpStream> ptr = weak_factory_.GetWeakPtr(); |
533 error_callback_.Run(message); | 537 error_callback_.Run(message); |
534 content::RenderThread::Get()->GetMessageLoop()->PostTask( | 538 content::RenderThread::Get()->GetMessageLoop()->PostTask( |
535 FROM_HERE, | 539 FROM_HERE, |
536 base::Bind(&CastRtpStream::Stop, ptr)); | 540 base::Bind(&CastRtpStream::Stop, ptr)); |
537 } | 541 } |
OLD | NEW |