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 "content/renderer/media/media_stream_dependency_factory.h" | 7 #include "content/renderer/media/media_stream_dependency_factory.h" |
8 #include "content/renderer/media/media_stream_video_source.h" | |
9 #include "content/renderer/media/webrtc/webrtc_video_sink_adapter.h" | 8 #include "content/renderer/media/webrtc/webrtc_video_sink_adapter.h" |
10 | 9 |
11 namespace content { | 10 namespace content { |
12 | 11 |
13 // Wrapper which allows to use std::find_if() when adding and removing | 12 // Empty method used for keeping a reference to the original media::VideoFrame |
14 // sinks to/from |sinks_|. | 13 // in RTCVideoRenderer::OnVideoFrame if a color conversion between I420 and |
15 struct SinkWrapper { | 14 // YV12 is needed. |
16 explicit SinkWrapper(MediaStreamVideoSink* sink) : sink_(sink) {} | 15 static void ReleaseOriginalFrame( |
17 bool operator()( | 16 const scoped_refptr<media::VideoFrame>& frame) { |
18 const WebRtcVideoSinkAdapter* owner) { | 17 } |
19 return owner->sink() == sink_; | |
20 } | |
21 MediaStreamVideoSink* sink_; | |
22 }; | |
23 | 18 |
24 MediaStreamVideoTrack::MediaStreamVideoTrack( | 19 //static |
25 webrtc::VideoTrackInterface* track) | 20 blink::WebMediaStreamTrack MediaStreamVideoTrack::CreateVideoTrack( |
26 : MediaStreamTrack(track, false), | 21 MediaStreamVideoSource* source, |
27 factory_(NULL) { | 22 const blink::WebMediaConstraints& constraints, |
| 23 const MediaStreamVideoSource::ConstraintsCallback& callback, |
| 24 bool enabled, |
| 25 MediaStreamDependencyFactory* factory) { |
| 26 blink::WebMediaStreamTrack track; |
| 27 track.initialize(source->owner()); |
| 28 track.setExtraData(new MediaStreamVideoTrack(source, |
| 29 constraints, |
| 30 callback, |
| 31 enabled, |
| 32 factory)); |
| 33 return track; |
| 34 } |
| 35 |
| 36 // static |
| 37 MediaStreamVideoTrack* MediaStreamVideoTrack::GetVideoTrack( |
| 38 const blink::WebMediaStreamTrack& track) { |
| 39 return static_cast<MediaStreamVideoTrack*>(track.extraData()); |
28 } | 40 } |
29 | 41 |
30 MediaStreamVideoTrack::MediaStreamVideoTrack( | 42 MediaStreamVideoTrack::MediaStreamVideoTrack( |
| 43 MediaStreamVideoSource* source, |
| 44 const blink::WebMediaConstraints& constraints, |
| 45 const MediaStreamVideoSource::ConstraintsCallback& callback, |
| 46 bool enabled, |
31 MediaStreamDependencyFactory* factory) | 47 MediaStreamDependencyFactory* factory) |
32 : MediaStreamTrack(NULL, true), | 48 : MediaStreamTrack(NULL, true), |
| 49 enabled_(enabled), |
| 50 source_(source), |
33 factory_(factory) { | 51 factory_(factory) { |
34 DCHECK(factory_); | 52 // TODO(perkj): source can be NULL if this is actually a remote video track. |
| 53 // Remove as soon as we only have one implementation of video tracks. |
| 54 if (source) |
| 55 source->AddTrack(this, constraints, callback); |
35 } | 56 } |
36 | 57 |
37 MediaStreamVideoTrack::~MediaStreamVideoTrack() { | 58 MediaStreamVideoTrack::~MediaStreamVideoTrack() { |
38 DCHECK(sinks_.empty()); | 59 DCHECK(sinks_.empty()); |
| 60 // TODO(perkj): source can be NULL if this is actually a remote video track. |
| 61 // Remove as soon as we only have one implementation of video tracks. |
| 62 if (source_) |
| 63 source_->RemoveTrack(this); |
39 } | 64 } |
40 | 65 |
41 void MediaStreamVideoTrack::AddSink(MediaStreamVideoSink* sink) { | 66 void MediaStreamVideoTrack::AddSink(MediaStreamVideoSink* sink) { |
42 DCHECK(thread_checker_.CalledOnValidThread()); | 67 DCHECK(thread_checker_.CalledOnValidThread()); |
43 DCHECK(std::find_if(sinks_.begin(), sinks_.end(), | 68 DCHECK(std::find(sinks_.begin(), sinks_.end(), sink) == sinks_.end()); |
44 SinkWrapper(sink)) == sinks_.end()); | 69 sinks_.push_back(sink); |
45 sinks_.push_back(new WebRtcVideoSinkAdapter(GetVideoAdapter(), sink)); | |
46 } | 70 } |
47 | 71 |
48 void MediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) { | 72 void MediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) { |
49 DCHECK(thread_checker_.CalledOnValidThread()); | 73 DCHECK(thread_checker_.CalledOnValidThread()); |
50 ScopedVector<WebRtcVideoSinkAdapter>::iterator it = | 74 std::vector<MediaStreamVideoSink*>::iterator it = |
51 std::find_if(sinks_.begin(), sinks_.end(), SinkWrapper(sink)); | 75 std::find(sinks_.begin(), sinks_.end(), sink); |
52 DCHECK(it != sinks_.end()); | 76 DCHECK(it != sinks_.end()); |
53 sinks_.erase(it); | 77 sinks_.erase(it); |
54 } | 78 } |
55 | 79 |
56 webrtc::VideoTrackInterface* MediaStreamVideoTrack::GetVideoAdapter() { | 80 webrtc::VideoTrackInterface* MediaStreamVideoTrack::GetVideoAdapter() { |
| 81 DCHECK(thread_checker_.CalledOnValidThread()); |
57 DCHECK_EQ(owner().source().type(), blink::WebMediaStreamSource::TypeVideo); | 82 DCHECK_EQ(owner().source().type(), blink::WebMediaStreamSource::TypeVideo); |
58 if (!track_.get()) { | 83 if (!track_.get()) { |
59 MediaStreamVideoSource* source = | 84 MediaStreamVideoSource* source = |
60 static_cast<MediaStreamVideoSource*>(owner().source().extraData()); | 85 static_cast<MediaStreamVideoSource*>(owner().source().extraData()); |
61 scoped_refptr<webrtc::VideoTrackInterface> video_track( | 86 scoped_refptr<webrtc::VideoTrackInterface> video_track( |
62 factory_->CreateLocalVideoTrack(owner().id().utf8(), | 87 factory_->CreateLocalVideoTrack(owner().id().utf8(), |
63 source->GetAdapter())); | 88 source->GetAdapter())); |
64 video_track->set_enabled(owner().isEnabled()); | 89 video_track->set_enabled(owner().isEnabled()); |
65 track_ = video_track; | 90 track_ = video_track; |
66 } | 91 } |
67 return static_cast<webrtc::VideoTrackInterface*>(track_.get()); | 92 return static_cast<webrtc::VideoTrackInterface*>(track_.get()); |
68 } | 93 } |
69 | 94 |
| 95 void MediaStreamVideoTrack::SetEnabled(bool enabled) { |
| 96 DCHECK(thread_checker_.CalledOnValidThread()); |
| 97 enabled_ = enabled; |
| 98 MediaStreamTrack::SetEnabled(enabled); |
| 99 for (std::vector<MediaStreamVideoSink*>::iterator it = sinks_.begin(); |
| 100 it != sinks_.end(); ++it) { |
| 101 (*it)->OnEnabledChanged(enabled); |
| 102 } |
| 103 } |
| 104 |
| 105 void MediaStreamVideoTrack::OnVideoFrame( |
| 106 const scoped_refptr<media::VideoFrame>& frame) { |
| 107 DCHECK(thread_checker_.CalledOnValidThread()); |
| 108 if (!enabled_) |
| 109 return; |
| 110 |
| 111 scoped_refptr<media::VideoFrame> video_frame = frame; |
| 112 if (frame->format() == media::VideoFrame::I420) { |
| 113 // Rendering do not support I420 but video capture use I420. |
| 114 // The only difference between YV12 and I420 is the order of U and V plane. |
| 115 // To solve that the I420 frame is simply wrapped in an YV12 video frame. |
| 116 // crbug/341452. |
| 117 video_frame = media::VideoFrame::WrapExternalYuvData( |
| 118 media::VideoFrame::YV12, |
| 119 frame->coded_size(), |
| 120 frame->visible_rect(), |
| 121 frame->natural_size(), |
| 122 frame->stride(media::VideoFrame::kYPlane), |
| 123 frame->stride(media::VideoFrame::kUPlane), |
| 124 frame->stride(media::VideoFrame::kVPlane), |
| 125 frame->data(media::VideoFrame::kYPlane), |
| 126 frame->data(media::VideoFrame::kUPlane), |
| 127 frame->data(media::VideoFrame::kVPlane), |
| 128 frame->GetTimestamp(), |
| 129 base::Bind(&ReleaseOriginalFrame, frame)); |
| 130 } |
| 131 |
| 132 for (std::vector<MediaStreamVideoSink*>::iterator it = sinks_.begin(); |
| 133 it != sinks_.end(); ++it) { |
| 134 (*it)->OnVideoFrame(video_frame); |
| 135 } |
| 136 } |
| 137 |
| 138 void MediaStreamVideoTrack::OnReadyStateChanged( |
| 139 blink::WebMediaStreamSource::ReadyState state) { |
| 140 DCHECK(thread_checker_.CalledOnValidThread()); |
| 141 for (std::vector<MediaStreamVideoSink*>::iterator it = sinks_.begin(); |
| 142 it != sinks_.end(); ++it) { |
| 143 (*it)->OnReadyStateChanged(state); |
| 144 } |
| 145 } |
| 146 |
| 147 // Wrapper which allows to use std::find_if() when adding and removing |
| 148 // sinks to/from |sinks_|. |
| 149 struct SinkWrapper { |
| 150 explicit SinkWrapper(MediaStreamVideoSink* sink) : sink_(sink) {} |
| 151 bool operator()( |
| 152 const WebRtcVideoSinkAdapter* owner) { |
| 153 return owner->sink() == sink_; |
| 154 } |
| 155 MediaStreamVideoSink* sink_; |
| 156 }; |
| 157 |
| 158 WebRtcMediaStreamVideoTrack::WebRtcMediaStreamVideoTrack( |
| 159 webrtc::VideoTrackInterface* track) |
| 160 : MediaStreamVideoTrack(NULL, |
| 161 blink::WebMediaConstraints(), |
| 162 MediaStreamVideoSource::ConstraintsCallback(), |
| 163 track->enabled(), |
| 164 NULL) { |
| 165 track_ = track; |
| 166 } |
| 167 |
| 168 WebRtcMediaStreamVideoTrack::~WebRtcMediaStreamVideoTrack() { |
| 169 } |
| 170 |
| 171 void WebRtcMediaStreamVideoTrack::AddSink(MediaStreamVideoSink* sink) { |
| 172 DCHECK(thread_checker_.CalledOnValidThread()); |
| 173 DCHECK(std::find_if(sinks_.begin(), sinks_.end(), |
| 174 SinkWrapper(sink)) == sinks_.end()); |
| 175 sinks_.push_back(new WebRtcVideoSinkAdapter(GetVideoAdapter(), sink)); |
| 176 } |
| 177 |
| 178 void WebRtcMediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) { |
| 179 DCHECK(thread_checker_.CalledOnValidThread()); |
| 180 ScopedVector<WebRtcVideoSinkAdapter>::iterator it = |
| 181 std::find_if(sinks_.begin(), sinks_.end(), SinkWrapper(sink)); |
| 182 DCHECK(it != sinks_.end()); |
| 183 sinks_.erase(it); |
| 184 } |
| 185 |
70 } // namespace content | 186 } // namespace content |
OLD | NEW |