| 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 "content/renderer/media/media_stream_video_track.h" | 5 #include "content/renderer/media/media_stream_video_track.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" | 10 #include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" |
| 11 | 11 |
| 12 namespace content { | 12 namespace content { |
| 13 | 13 |
| 14 namespace { | 14 namespace { |
| 15 void ResetCallback(scoped_ptr<VideoCaptureDeliverFrameCB> callback) { | 15 void ResetCallback(scoped_ptr<VideoCaptureDeliverFrameCB> callback) { |
| 16 // |callback| will be deleted when this exits. | 16 // |callback| will be deleted when this exits. |
| 17 } | 17 } |
| 18 } // namespace | 18 } // namespace |
| 19 | 19 |
| 20 // MediaStreamVideoTrack::FrameDeliverer is a helper class used for registering | 20 // MediaStreamVideoTrack::FrameDeliverer is a helper class used for registering |
| 21 // VideoCaptureDeliverFrameCB on the main render thread to receive video frames | 21 // VideoCaptureDeliverFrameCB on the main render thread to receive video frames |
| 22 // on the IO-thread. | 22 // on the IO-thread. |
| 23 // Frames are only delivered to the sinks if the track is enabled. If the track | 23 // Frames are only delivered to the sinks if the track is enabled. If the track |
| 24 // is disabled, a black frame is instead forwarded to the sinks at the same | 24 // is disabled, a black frame is instead forwarded to the sinks at the same |
| 25 // frame rate. | 25 // frame rate. |
| 26 class MediaStreamVideoTrack::FrameDeliverer | 26 class MediaStreamVideoTrack::FrameDeliverer |
| 27 : public base::RefCountedThreadSafe<FrameDeliverer> { | 27 : public base::RefCountedThreadSafe<FrameDeliverer> { |
| 28 public: | 28 public: |
| 29 typedef MediaStreamVideoSink* VideoSinkId; |
| 30 |
| 29 FrameDeliverer( | 31 FrameDeliverer( |
| 30 const scoped_refptr<base::MessageLoopProxy>& io_message_loop, | 32 const scoped_refptr<base::MessageLoopProxy>& io_message_loop, |
| 31 bool enabled); | 33 bool enabled); |
| 32 | 34 |
| 33 void SetEnabled(bool enabled); | 35 void SetEnabled(bool enabled); |
| 34 | 36 |
| 35 // Add |callback| to receive video frames on the IO-thread. | 37 // Add |callback| to receive video frames on the IO-thread. |
| 36 // Must be called on the main render thread. | 38 // Must be called on the main render thread. |
| 37 void AddCallback(void* id, const VideoCaptureDeliverFrameCB& callback); | 39 void AddCallback(VideoSinkId id, const VideoCaptureDeliverFrameCB& callback); |
| 38 | 40 |
| 39 // Removes |callback| associated with |id| from receiving video frames if |id| | 41 // Removes |callback| associated with |id| from receiving video frames if |id| |
| 40 // has been added. It is ok to call RemoveCallback even if the |id| has not | 42 // has been added. It is ok to call RemoveCallback even if the |id| has not |
| 41 // been added. Note that the added callback will be reset on the main thread. | 43 // been added. Note that the added callback will be reset on the main thread. |
| 42 // Must be called on the main render thread. | 44 // Must be called on the main render thread. |
| 43 void RemoveCallback(void* id); | 45 void RemoveCallback(VideoSinkId id); |
| 44 | 46 |
| 45 // Triggers all registered callbacks with |frame|, |format| and | 47 // Triggers all registered callbacks with |frame|, |format| and |
| 46 // |estimated_capture_time| as parameters. Must be called on the IO-thread. | 48 // |estimated_capture_time| as parameters. Must be called on the IO-thread. |
| 47 void DeliverFrameOnIO(const scoped_refptr<media::VideoFrame>& frame, | 49 void DeliverFrameOnIO(const scoped_refptr<media::VideoFrame>& frame, |
| 48 const base::TimeTicks& estimated_capture_time); | 50 const base::TimeTicks& estimated_capture_time); |
| 49 | 51 |
| 50 private: | 52 private: |
| 51 friend class base::RefCountedThreadSafe<FrameDeliverer>; | 53 friend class base::RefCountedThreadSafe<FrameDeliverer>; |
| 52 virtual ~FrameDeliverer(); | 54 virtual ~FrameDeliverer(); |
| 53 void AddCallbackOnIO(void* id, const VideoCaptureDeliverFrameCB& callback); | 55 void AddCallbackOnIO(VideoSinkId id, |
| 56 const VideoCaptureDeliverFrameCB& callback); |
| 54 void RemoveCallbackOnIO( | 57 void RemoveCallbackOnIO( |
| 55 void* id, const scoped_refptr<base::MessageLoopProxy>& message_loop); | 58 VideoSinkId id, |
| 59 const scoped_refptr<base::MessageLoopProxy>& message_loop); |
| 56 | 60 |
| 57 void SetEnabledOnIO(bool enabled); | 61 void SetEnabledOnIO(bool enabled); |
| 58 // Returns |black_frame_| where the size and time stamp is set to the same as | 62 // Returns |black_frame_| where the size and time stamp is set to the same as |
| 59 // as in |reference_frame|. | 63 // as in |reference_frame|. |
| 60 const scoped_refptr<media::VideoFrame>& GetBlackFrame( | 64 const scoped_refptr<media::VideoFrame>& GetBlackFrame( |
| 61 const scoped_refptr<media::VideoFrame>& reference_frame); | 65 const scoped_refptr<media::VideoFrame>& reference_frame); |
| 62 | 66 |
| 63 // Used to DCHECK that AddCallback and RemoveCallback are called on the main | 67 // Used to DCHECK that AddCallback and RemoveCallback are called on the main |
| 64 // render thread. | 68 // Render Thread. |
| 65 base::ThreadChecker thread_checker_; | 69 base::ThreadChecker main_render_thread_checker_; |
| 66 scoped_refptr<base::MessageLoopProxy> io_message_loop_; | 70 const scoped_refptr<base::MessageLoopProxy> io_message_loop_; |
| 67 | 71 |
| 68 bool enabled_; | 72 bool enabled_; |
| 69 scoped_refptr<media::VideoFrame> black_frame_; | 73 scoped_refptr<media::VideoFrame> black_frame_; |
| 70 | 74 |
| 71 typedef std::pair<void*, VideoCaptureDeliverFrameCB> VideoIdCallbackPair; | 75 typedef std::pair<VideoSinkId, VideoCaptureDeliverFrameCB> |
| 76 VideoIdCallbackPair; |
| 72 std::vector<VideoIdCallbackPair> callbacks_; | 77 std::vector<VideoIdCallbackPair> callbacks_; |
| 73 | 78 |
| 74 DISALLOW_COPY_AND_ASSIGN(FrameDeliverer); | 79 DISALLOW_COPY_AND_ASSIGN(FrameDeliverer); |
| 75 }; | 80 }; |
| 76 | 81 |
| 77 MediaStreamVideoTrack::FrameDeliverer::FrameDeliverer( | 82 MediaStreamVideoTrack::FrameDeliverer::FrameDeliverer( |
| 78 const scoped_refptr<base::MessageLoopProxy>& io_message_loop, bool enabled) | 83 const scoped_refptr<base::MessageLoopProxy>& io_message_loop, bool enabled) |
| 79 : io_message_loop_(io_message_loop), | 84 : io_message_loop_(io_message_loop), |
| 80 enabled_(enabled) { | 85 enabled_(enabled) { |
| 81 DCHECK(io_message_loop_.get()); | 86 DCHECK(io_message_loop_.get()); |
| 82 } | 87 } |
| 83 | 88 |
| 84 MediaStreamVideoTrack::FrameDeliverer::~FrameDeliverer() { | 89 MediaStreamVideoTrack::FrameDeliverer::~FrameDeliverer() { |
| 85 DCHECK(callbacks_.empty()); | 90 DCHECK(callbacks_.empty()); |
| 86 } | 91 } |
| 87 | 92 |
| 88 void MediaStreamVideoTrack::FrameDeliverer::AddCallback( | 93 void MediaStreamVideoTrack::FrameDeliverer::AddCallback( |
| 89 void* id, | 94 VideoSinkId id, |
| 90 const VideoCaptureDeliverFrameCB& callback) { | 95 const VideoCaptureDeliverFrameCB& callback) { |
| 91 DCHECK(thread_checker_.CalledOnValidThread()); | 96 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 92 io_message_loop_->PostTask( | 97 io_message_loop_->PostTask( |
| 93 FROM_HERE, | 98 FROM_HERE, |
| 94 base::Bind(&FrameDeliverer::AddCallbackOnIO, | 99 base::Bind(&FrameDeliverer::AddCallbackOnIO, |
| 95 this, id, callback)); | 100 this, id, callback)); |
| 96 } | 101 } |
| 97 | 102 |
| 98 void MediaStreamVideoTrack::FrameDeliverer::AddCallbackOnIO( | 103 void MediaStreamVideoTrack::FrameDeliverer::AddCallbackOnIO( |
| 99 void* id, | 104 VideoSinkId id, |
| 100 const VideoCaptureDeliverFrameCB& callback) { | 105 const VideoCaptureDeliverFrameCB& callback) { |
| 101 DCHECK(io_message_loop_->BelongsToCurrentThread()); | 106 DCHECK(io_message_loop_->BelongsToCurrentThread()); |
| 102 callbacks_.push_back(std::make_pair(id, callback)); | 107 callbacks_.push_back(std::make_pair(id, callback)); |
| 103 } | 108 } |
| 104 | 109 |
| 105 void MediaStreamVideoTrack::FrameDeliverer::RemoveCallback(void* id) { | 110 void MediaStreamVideoTrack::FrameDeliverer::RemoveCallback(VideoSinkId id) { |
| 106 DCHECK(thread_checker_.CalledOnValidThread()); | 111 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 107 io_message_loop_->PostTask( | 112 io_message_loop_->PostTask( |
| 108 FROM_HERE, | 113 FROM_HERE, |
| 109 base::Bind(&FrameDeliverer::RemoveCallbackOnIO, | 114 base::Bind(&FrameDeliverer::RemoveCallbackOnIO, |
| 110 this, id, base::MessageLoopProxy::current())); | 115 this, id, base::MessageLoopProxy::current())); |
| 111 } | 116 } |
| 112 | 117 |
| 113 void MediaStreamVideoTrack::FrameDeliverer::RemoveCallbackOnIO( | 118 void MediaStreamVideoTrack::FrameDeliverer::RemoveCallbackOnIO( |
| 114 void* id, const scoped_refptr<base::MessageLoopProxy>& message_loop) { | 119 VideoSinkId id, |
| 120 const scoped_refptr<base::MessageLoopProxy>& message_loop) { |
| 115 DCHECK(io_message_loop_->BelongsToCurrentThread()); | 121 DCHECK(io_message_loop_->BelongsToCurrentThread()); |
| 116 std::vector<VideoIdCallbackPair>::iterator it = callbacks_.begin(); | 122 std::vector<VideoIdCallbackPair>::iterator it = callbacks_.begin(); |
| 117 for (; it != callbacks_.end(); ++it) { | 123 for (; it != callbacks_.end(); ++it) { |
| 118 if (it->first == id) { | 124 if (it->first == id) { |
| 119 // Callback is copied to heap and then deleted on the target thread. | 125 // Callback is copied to heap and then deleted on the target thread. |
| 120 scoped_ptr<VideoCaptureDeliverFrameCB> callback; | 126 scoped_ptr<VideoCaptureDeliverFrameCB> callback; |
| 121 callback.reset(new VideoCaptureDeliverFrameCB(it->second)); | 127 callback.reset(new VideoCaptureDeliverFrameCB(it->second)); |
| 122 callbacks_.erase(it); | 128 callbacks_.erase(it); |
| 123 message_loop->PostTask( | 129 message_loop->PostTask( |
| 124 FROM_HERE, base::Bind(&ResetCallback, base::Passed(&callback))); | 130 FROM_HERE, base::Bind(&ResetCallback, base::Passed(&callback))); |
| 125 return; | 131 return; |
| 126 } | 132 } |
| 127 } | 133 } |
| 128 } | 134 } |
| 129 | 135 |
| 130 void MediaStreamVideoTrack::FrameDeliverer::SetEnabled(bool enabled) { | 136 void MediaStreamVideoTrack::FrameDeliverer::SetEnabled(bool enabled) { |
| 131 DCHECK(thread_checker_.CalledOnValidThread()); | 137 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 132 io_message_loop_->PostTask( | 138 io_message_loop_->PostTask( |
| 133 FROM_HERE, | 139 FROM_HERE, |
| 134 base::Bind(&FrameDeliverer::SetEnabledOnIO, | 140 base::Bind(&FrameDeliverer::SetEnabledOnIO, |
| 135 this, enabled)); | 141 this, enabled)); |
| 136 } | 142 } |
| 137 | 143 |
| 138 void MediaStreamVideoTrack::FrameDeliverer::SetEnabledOnIO(bool enabled) { | 144 void MediaStreamVideoTrack::FrameDeliverer::SetEnabledOnIO(bool enabled) { |
| 139 DCHECK(io_message_loop_->BelongsToCurrentThread()); | 145 DCHECK(io_message_loop_->BelongsToCurrentThread()); |
| 140 enabled_ = enabled; | 146 enabled_ = enabled; |
| 141 if (enabled_) | 147 if (enabled_) |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 source_(source) { | 205 source_(source) { |
| 200 DCHECK(!constraints.isNull()); | 206 DCHECK(!constraints.isNull()); |
| 201 source->AddTrack(this, | 207 source->AddTrack(this, |
| 202 base::Bind( | 208 base::Bind( |
| 203 &MediaStreamVideoTrack::FrameDeliverer::DeliverFrameOnIO, | 209 &MediaStreamVideoTrack::FrameDeliverer::DeliverFrameOnIO, |
| 204 frame_deliverer_), | 210 frame_deliverer_), |
| 205 constraints, callback); | 211 constraints, callback); |
| 206 } | 212 } |
| 207 | 213 |
| 208 MediaStreamVideoTrack::~MediaStreamVideoTrack() { | 214 MediaStreamVideoTrack::~MediaStreamVideoTrack() { |
| 209 DCHECK(thread_checker_.CalledOnValidThread()); | 215 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 210 DCHECK(sinks_.empty()); | 216 DCHECK(sinks_.empty()); |
| 211 Stop(); | 217 Stop(); |
| 212 DVLOG(3) << "~MediaStreamVideoTrack()"; | 218 DVLOG(3) << "~MediaStreamVideoTrack()"; |
| 213 } | 219 } |
| 214 | 220 |
| 215 void MediaStreamVideoTrack::AddSink( | 221 void MediaStreamVideoTrack::AddSink( |
| 216 MediaStreamVideoSink* sink, const VideoCaptureDeliverFrameCB& callback) { | 222 MediaStreamVideoSink* sink, const VideoCaptureDeliverFrameCB& callback) { |
| 217 DCHECK(thread_checker_.CalledOnValidThread()); | 223 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 218 DCHECK(std::find(sinks_.begin(), sinks_.end(), sink) == sinks_.end()); | 224 DCHECK(std::find(sinks_.begin(), sinks_.end(), sink) == sinks_.end()); |
| 219 sinks_.push_back(sink); | 225 sinks_.push_back(sink); |
| 220 frame_deliverer_->AddCallback(sink, callback); | 226 frame_deliverer_->AddCallback(sink, callback); |
| 221 } | 227 } |
| 222 | 228 |
| 223 void MediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) { | 229 void MediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) { |
| 224 DCHECK(thread_checker_.CalledOnValidThread()); | 230 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 225 std::vector<MediaStreamVideoSink*>::iterator it = | 231 std::vector<MediaStreamVideoSink*>::iterator it = |
| 226 std::find(sinks_.begin(), sinks_.end(), sink); | 232 std::find(sinks_.begin(), sinks_.end(), sink); |
| 227 DCHECK(it != sinks_.end()); | 233 DCHECK(it != sinks_.end()); |
| 228 sinks_.erase(it); | 234 sinks_.erase(it); |
| 229 frame_deliverer_->RemoveCallback(sink); | 235 frame_deliverer_->RemoveCallback(sink); |
| 230 } | 236 } |
| 231 | 237 |
| 232 void MediaStreamVideoTrack::SetEnabled(bool enabled) { | 238 void MediaStreamVideoTrack::SetEnabled(bool enabled) { |
| 233 DCHECK(thread_checker_.CalledOnValidThread()); | 239 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 234 frame_deliverer_->SetEnabled(enabled); | 240 frame_deliverer_->SetEnabled(enabled); |
| 235 for (std::vector<MediaStreamVideoSink*>::const_iterator it = sinks_.begin(); | 241 for (auto* sink : sinks_) |
| 236 it != sinks_.end(); ++it) { | 242 sink->OnEnabledChanged(enabled); |
| 237 (*it)->OnEnabledChanged(enabled); | |
| 238 } | |
| 239 } | 243 } |
| 240 | 244 |
| 241 void MediaStreamVideoTrack::Stop() { | 245 void MediaStreamVideoTrack::Stop() { |
| 242 DCHECK(thread_checker_.CalledOnValidThread()); | 246 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 243 if (source_) { | 247 if (source_) { |
| 244 source_->RemoveTrack(this); | 248 source_->RemoveTrack(this); |
| 245 source_ = NULL; | 249 source_ = NULL; |
| 246 } | 250 } |
| 247 OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateEnded); | 251 OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateEnded); |
| 248 } | 252 } |
| 249 | 253 |
| 250 void MediaStreamVideoTrack::OnReadyStateChanged( | 254 void MediaStreamVideoTrack::OnReadyStateChanged( |
| 251 blink::WebMediaStreamSource::ReadyState state) { | 255 blink::WebMediaStreamSource::ReadyState state) { |
| 252 DCHECK(thread_checker_.CalledOnValidThread()); | 256 DCHECK(main_render_thread_checker_.CalledOnValidThread()); |
| 253 for (std::vector<MediaStreamVideoSink*>::const_iterator it = sinks_.begin(); | 257 for (auto* sink : sinks_) |
| 254 it != sinks_.end(); ++it) { | 258 sink->OnReadyStateChanged(state); |
| 255 (*it)->OnReadyStateChanged(state); | |
| 256 } | |
| 257 } | 259 } |
| 258 | 260 |
| 259 } // namespace content | 261 } // namespace content |
| OLD | NEW |