| 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::VideoFrame::kFrameRateMetadataKey, |
| 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 |