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 "content/renderer/media/video_track_adapter.h" | 5 #include "content/renderer/media/video_track_adapter.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 // |callback| will however be released on the main render thread. | 69 // |callback| will however be released on the main render thread. |
70 void AddCallback(const MediaStreamVideoTrack* track, | 70 void AddCallback(const MediaStreamVideoTrack* track, |
71 const VideoCaptureDeliverFrameCB& callback); | 71 const VideoCaptureDeliverFrameCB& callback); |
72 | 72 |
73 // Removes |callback| associated with |track| from receiving video frames if | 73 // Removes |callback| associated with |track| from receiving video frames if |
74 // |track| has been added. It is ok to call RemoveCallback even if the |track| | 74 // |track| has been added. It is ok to call RemoveCallback even if the |track| |
75 // has not been added. The |callback| is released on the main render thread. | 75 // has not been added. The |callback| is released on the main render thread. |
76 void RemoveCallback(const MediaStreamVideoTrack* track); | 76 void RemoveCallback(const MediaStreamVideoTrack* track); |
77 | 77 |
78 void DeliverFrame(const scoped_refptr<media::VideoFrame>& frame, | 78 void DeliverFrame(const scoped_refptr<media::VideoFrame>& frame, |
79 const media::VideoCaptureFormat& format, | |
80 const base::TimeTicks& estimated_capture_time); | 79 const base::TimeTicks& estimated_capture_time); |
81 | 80 |
82 // Returns true if all arguments match with the output of this adapter. | 81 // Returns true if all arguments match with the output of this adapter. |
83 bool ConstraintsMatch(const gfx::Size& max_size, | 82 bool ConstraintsMatch(const gfx::Size& max_size, |
84 double min_aspect_ratio, | 83 double min_aspect_ratio, |
85 double max_aspect_ratio, | 84 double max_aspect_ratio, |
86 double max_frame_rate) const; | 85 double max_frame_rate) const; |
87 | 86 |
88 bool IsEmpty() const; | 87 bool IsEmpty() const; |
89 | 88 |
90 private: | 89 private: |
91 virtual ~VideoFrameResolutionAdapter(); | 90 virtual ~VideoFrameResolutionAdapter(); |
92 friend class base::RefCountedThreadSafe<VideoFrameResolutionAdapter>; | 91 friend class base::RefCountedThreadSafe<VideoFrameResolutionAdapter>; |
93 | 92 |
94 virtual void DoDeliverFrame( | 93 virtual void DoDeliverFrame( |
95 const scoped_refptr<media::VideoFrame>& frame, | 94 const scoped_refptr<media::VideoFrame>& frame, |
96 const media::VideoCaptureFormat& format, | |
97 const base::TimeTicks& estimated_capture_time); | 95 const base::TimeTicks& estimated_capture_time); |
98 | 96 |
99 // Returns |true| if the input frame rate is higher that the requested max | 97 // Returns |true| if the input frame rate is higher that the requested max |
100 // frame rate and |frame| should be dropped. | 98 // frame rate and |frame| should be dropped. |
101 bool MaybeDropFrame(const scoped_refptr<media::VideoFrame>& frame, | 99 bool MaybeDropFrame(const scoped_refptr<media::VideoFrame>& frame, |
102 float source_frame_rate); | 100 float source_frame_rate); |
103 | 101 |
104 // Bound to the IO-thread. | 102 // Bound to the IO-thread. |
105 base::ThreadChecker io_thread_checker_; | 103 base::ThreadChecker io_thread_checker_; |
106 | 104 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 } | 165 } |
168 | 166 |
169 VideoTrackAdapter:: | 167 VideoTrackAdapter:: |
170 VideoFrameResolutionAdapter::~VideoFrameResolutionAdapter() { | 168 VideoFrameResolutionAdapter::~VideoFrameResolutionAdapter() { |
171 DCHECK(io_thread_checker_.CalledOnValidThread()); | 169 DCHECK(io_thread_checker_.CalledOnValidThread()); |
172 DCHECK(callbacks_.empty()); | 170 DCHECK(callbacks_.empty()); |
173 } | 171 } |
174 | 172 |
175 void VideoTrackAdapter::VideoFrameResolutionAdapter::DeliverFrame( | 173 void VideoTrackAdapter::VideoFrameResolutionAdapter::DeliverFrame( |
176 const scoped_refptr<media::VideoFrame>& frame, | 174 const scoped_refptr<media::VideoFrame>& frame, |
177 const media::VideoCaptureFormat& format, | |
178 const base::TimeTicks& estimated_capture_time) { | 175 const base::TimeTicks& estimated_capture_time) { |
179 DCHECK(io_thread_checker_.CalledOnValidThread()); | 176 DCHECK(io_thread_checker_.CalledOnValidThread()); |
180 | 177 |
181 if (MaybeDropFrame(frame, format.frame_rate)) | 178 double frame_rate; |
| 179 if (!frame->metadata().GetDouble(media::VideoFrameMetadata::FRAME_RATE, |
| 180 &frame_rate)) |
| 181 frame_rate = MediaStreamVideoSource::kUnknownFrameRate; |
| 182 if (MaybeDropFrame(frame, frame_rate)) |
182 return; | 183 return; |
183 | 184 |
184 // TODO(perkj): Allow cropping / scaling of textures once | 185 // TODO(perkj): Allow cropping / scaling of textures once |
185 // http://crbug/362521 is fixed. | 186 // http://crbug/362521 is fixed. |
186 if (frame->format() == media::VideoFrame::NATIVE_TEXTURE) { | 187 if (frame->format() == media::VideoFrame::NATIVE_TEXTURE) { |
187 DoDeliverFrame(frame, format, estimated_capture_time); | 188 DoDeliverFrame(frame, estimated_capture_time); |
188 return; | 189 return; |
189 } | 190 } |
190 scoped_refptr<media::VideoFrame> video_frame(frame); | 191 scoped_refptr<media::VideoFrame> video_frame(frame); |
191 double input_ratio = | 192 double input_ratio = |
192 static_cast<double>(frame->natural_size().width()) / | 193 static_cast<double>(frame->natural_size().width()) / |
193 frame->natural_size().height(); | 194 frame->natural_size().height(); |
194 | 195 |
195 // If |frame| has larger width or height than requested, or the aspect ratio | 196 // If |frame| has larger width or height than requested, or the aspect ratio |
196 // does not match the requested, we want to create a wrapped version of this | 197 // does not match the requested, we want to create a wrapped version of this |
197 // frame with a size that fulfills the constraints. | 198 // frame with a size that fulfills the constraints. |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 region_in_frame, | 240 region_in_frame, |
240 desired_size, | 241 desired_size, |
241 base::Bind(&ReleaseOriginalFrame, frame)); | 242 base::Bind(&ReleaseOriginalFrame, frame)); |
242 | 243 |
243 DVLOG(3) << "desired size " << desired_size.ToString() | 244 DVLOG(3) << "desired size " << desired_size.ToString() |
244 << " output natural size " | 245 << " output natural size " |
245 << video_frame->natural_size().ToString() | 246 << video_frame->natural_size().ToString() |
246 << " output visible rect " | 247 << " output visible rect " |
247 << video_frame->visible_rect().ToString(); | 248 << video_frame->visible_rect().ToString(); |
248 } | 249 } |
249 DoDeliverFrame(video_frame, format, estimated_capture_time); | 250 DoDeliverFrame(video_frame, estimated_capture_time); |
250 } | 251 } |
251 | 252 |
252 bool VideoTrackAdapter::VideoFrameResolutionAdapter::MaybeDropFrame( | 253 bool VideoTrackAdapter::VideoFrameResolutionAdapter::MaybeDropFrame( |
253 const scoped_refptr<media::VideoFrame>& frame, | 254 const scoped_refptr<media::VideoFrame>& frame, |
254 float source_frame_rate) { | 255 float source_frame_rate) { |
255 DCHECK(io_thread_checker_.CalledOnValidThread()); | 256 DCHECK(io_thread_checker_.CalledOnValidThread()); |
256 | 257 |
257 // Do not drop frames if max frame rate hasn't been specified or the source | 258 // Do not drop frames if max frame rate hasn't been specified or the source |
258 // frame rate is known and is lower than max. | 259 // frame rate is known and is lower than max. |
259 if (max_frame_rate_ == 0.0f || | 260 if (max_frame_rate_ == 0.0f || |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 // Keep the frame. | 305 // Keep the frame. |
305 return false; | 306 return false; |
306 } | 307 } |
307 DVLOG(3) << "Drop frame. Input frame_rate_ " << frame_rate_ << "."; | 308 DVLOG(3) << "Drop frame. Input frame_rate_ " << frame_rate_ << "."; |
308 return true; | 309 return true; |
309 } | 310 } |
310 | 311 |
311 void VideoTrackAdapter:: | 312 void VideoTrackAdapter:: |
312 VideoFrameResolutionAdapter::DoDeliverFrame( | 313 VideoFrameResolutionAdapter::DoDeliverFrame( |
313 const scoped_refptr<media::VideoFrame>& frame, | 314 const scoped_refptr<media::VideoFrame>& frame, |
314 const media::VideoCaptureFormat& format, | |
315 const base::TimeTicks& estimated_capture_time) { | 315 const base::TimeTicks& estimated_capture_time) { |
316 DCHECK(io_thread_checker_.CalledOnValidThread()); | 316 DCHECK(io_thread_checker_.CalledOnValidThread()); |
317 for (std::vector<VideoIdCallbackPair>::const_iterator it = callbacks_.begin(); | 317 for (const auto& entry : callbacks_) |
318 it != callbacks_.end(); ++it) { | 318 entry.second.Run(frame, estimated_capture_time); |
319 it->second.Run(frame, format, estimated_capture_time); | |
320 } | |
321 } | 319 } |
322 | 320 |
323 void VideoTrackAdapter::VideoFrameResolutionAdapter::AddCallback( | 321 void VideoTrackAdapter::VideoFrameResolutionAdapter::AddCallback( |
324 const MediaStreamVideoTrack* track, | 322 const MediaStreamVideoTrack* track, |
325 const VideoCaptureDeliverFrameCB& callback) { | 323 const VideoCaptureDeliverFrameCB& callback) { |
326 DCHECK(io_thread_checker_.CalledOnValidThread()); | 324 DCHECK(io_thread_checker_.CalledOnValidThread()); |
327 callbacks_.push_back(std::make_pair(track, callback)); | 325 callbacks_.push_back(std::make_pair(track, callback)); |
328 } | 326 } |
329 | 327 |
330 void VideoTrackAdapter::VideoFrameResolutionAdapter::RemoveCallback( | 328 void VideoTrackAdapter::VideoFrameResolutionAdapter::RemoveCallback( |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 (*it)->RemoveCallback(track); | 485 (*it)->RemoveCallback(track); |
488 if ((*it)->IsEmpty()) { | 486 if ((*it)->IsEmpty()) { |
489 adapters_.erase(it); | 487 adapters_.erase(it); |
490 break; | 488 break; |
491 } | 489 } |
492 } | 490 } |
493 } | 491 } |
494 | 492 |
495 void VideoTrackAdapter::DeliverFrameOnIO( | 493 void VideoTrackAdapter::DeliverFrameOnIO( |
496 const scoped_refptr<media::VideoFrame>& frame, | 494 const scoped_refptr<media::VideoFrame>& frame, |
497 const media::VideoCaptureFormat& format, | |
498 const base::TimeTicks& estimated_capture_time) { | 495 const base::TimeTicks& estimated_capture_time) { |
499 DCHECK(io_message_loop_->BelongsToCurrentThread()); | 496 DCHECK(io_message_loop_->BelongsToCurrentThread()); |
500 TRACE_EVENT0("video", "VideoTrackAdapter::DeliverFrameOnIO"); | 497 TRACE_EVENT0("video", "VideoTrackAdapter::DeliverFrameOnIO"); |
501 ++frame_counter_; | 498 ++frame_counter_; |
502 for (FrameAdapters::iterator it = adapters_.begin(); | 499 for (const auto& adapter : adapters_) |
503 it != adapters_.end(); ++it) { | 500 adapter->DeliverFrame(frame, estimated_capture_time); |
504 (*it)->DeliverFrame(frame, format, estimated_capture_time); | |
505 } | |
506 } | 501 } |
507 | 502 |
508 void VideoTrackAdapter::CheckFramesReceivedOnIO( | 503 void VideoTrackAdapter::CheckFramesReceivedOnIO( |
509 const OnMutedCallback& set_muted_state_callback, | 504 const OnMutedCallback& set_muted_state_callback, |
510 uint64 old_frame_counter_snapshot) { | 505 uint64 old_frame_counter_snapshot) { |
511 DCHECK(io_message_loop_->BelongsToCurrentThread()); | 506 DCHECK(io_message_loop_->BelongsToCurrentThread()); |
512 | 507 |
513 if (!monitoring_frame_rate_) | 508 if (!monitoring_frame_rate_) |
514 return; | 509 return; |
515 | 510 |
516 DVLOG_IF(1, old_frame_counter_snapshot == frame_counter_) | 511 DVLOG_IF(1, old_frame_counter_snapshot == frame_counter_) |
517 << "No frames have passed, setting source as Muted."; | 512 << "No frames have passed, setting source as Muted."; |
518 | 513 |
519 bool muted_state = old_frame_counter_snapshot == frame_counter_; | 514 bool muted_state = old_frame_counter_snapshot == frame_counter_; |
520 if (muted_state_ != muted_state) { | 515 if (muted_state_ != muted_state) { |
521 set_muted_state_callback.Run(muted_state); | 516 set_muted_state_callback.Run(muted_state); |
522 muted_state_ = muted_state; | 517 muted_state_ = muted_state; |
523 } | 518 } |
524 | 519 |
525 io_message_loop_->PostDelayedTask(FROM_HERE, | 520 io_message_loop_->PostDelayedTask(FROM_HERE, |
526 base::Bind(&VideoTrackAdapter::CheckFramesReceivedOnIO, this, | 521 base::Bind(&VideoTrackAdapter::CheckFramesReceivedOnIO, this, |
527 set_muted_state_callback, frame_counter_), | 522 set_muted_state_callback, frame_counter_), |
528 base::TimeDelta::FromSecondsD(kNormalFrameTimeoutInFrameIntervals / | 523 base::TimeDelta::FromSecondsD(kNormalFrameTimeoutInFrameIntervals / |
529 source_frame_rate_)); | 524 source_frame_rate_)); |
530 } | 525 } |
531 | 526 |
532 } // namespace content | 527 } // namespace content |
OLD | NEW |