OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/rtc_video_decoder.h" | 5 #include "content/renderer/media/rtc_video_decoder.h" |
6 | 6 |
7 #include <deque> | 7 #include <deque> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 if (MessageLoop::current() != message_loop_) { | 46 if (MessageLoop::current() != message_loop_) { |
47 message_loop_->PostTask( | 47 message_loop_->PostTask( |
48 FROM_HERE, | 48 FROM_HERE, |
49 base::Bind(&RTCVideoDecoder::Initialize, this, | 49 base::Bind(&RTCVideoDecoder::Initialize, this, |
50 make_scoped_refptr(demuxer_stream), | 50 make_scoped_refptr(demuxer_stream), |
51 filter_callback, stat_callback)); | 51 filter_callback, stat_callback)); |
52 return; | 52 return; |
53 } | 53 } |
54 | 54 |
55 DCHECK_EQ(MessageLoop::current(), message_loop_); | 55 DCHECK_EQ(MessageLoop::current(), message_loop_); |
56 | |
57 lock_.Acquire(); | |
58 frame_queue_available_.clear(); | |
59 lock_.Release(); | |
60 | |
61 state_ = kNormal; | 56 state_ = kNormal; |
62 | |
63 filter_callback.Run(); | 57 filter_callback.Run(); |
64 | 58 |
65 // TODO(acolwell): Implement stats. | 59 // TODO(acolwell): Implement stats. |
66 } | 60 } |
67 | 61 |
68 void RTCVideoDecoder::Play(const base::Closure& callback) { | 62 void RTCVideoDecoder::Play(const base::Closure& callback) { |
69 if (MessageLoop::current() != message_loop_) { | 63 if (MessageLoop::current() != message_loop_) { |
70 message_loop_->PostTask(FROM_HERE, | 64 message_loop_->PostTask(FROM_HERE, |
71 base::Bind(&RTCVideoDecoder::Play, | 65 base::Bind(&RTCVideoDecoder::Play, |
72 this, callback)); | 66 this, callback)); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 | 104 |
111 void RTCVideoDecoder::Seek(base::TimeDelta time, const FilterStatusCB& cb) { | 105 void RTCVideoDecoder::Seek(base::TimeDelta time, const FilterStatusCB& cb) { |
112 if (MessageLoop::current() != message_loop_) { | 106 if (MessageLoop::current() != message_loop_) { |
113 message_loop_->PostTask(FROM_HERE, | 107 message_loop_->PostTask(FROM_HERE, |
114 base::Bind(&RTCVideoDecoder::Seek, this, | 108 base::Bind(&RTCVideoDecoder::Seek, this, |
115 time, cb)); | 109 time, cb)); |
116 return; | 110 return; |
117 } | 111 } |
118 | 112 |
119 DCHECK_EQ(MessageLoop::current(), message_loop_); | 113 DCHECK_EQ(MessageLoop::current(), message_loop_); |
120 | |
121 state_ = kSeeking; | |
122 // Create output buffer pool and pass the frames to renderer | |
123 // so that the renderer can complete the seeking. | |
124 for (size_t i = 0; i < Limits::kMaxVideoFrames; ++i) { | |
125 VideoFrameReady(VideoFrame::CreateBlackFrame( | |
126 visible_size_.width(), visible_size_.height())); | |
127 } | |
128 | |
129 state_ = kNormal; | 114 state_ = kNormal; |
130 | |
131 cb.Run(PIPELINE_OK); | 115 cb.Run(PIPELINE_OK); |
132 } | 116 } |
133 | 117 |
134 void RTCVideoDecoder::ProduceVideoFrame( | 118 void RTCVideoDecoder::Read(const ReadCB& callback) { |
135 scoped_refptr<VideoFrame> video_frame) { | |
136 if (MessageLoop::current() != message_loop_) { | 119 if (MessageLoop::current() != message_loop_) { |
137 message_loop_->PostTask( | 120 message_loop_->PostTask( |
138 FROM_HERE, | 121 FROM_HERE, |
139 base::Bind(&RTCVideoDecoder::ProduceVideoFrame, this, video_frame)); | 122 base::Bind(&RTCVideoDecoder::Read, this, callback)); |
140 return; | 123 return; |
141 } | 124 } |
142 DCHECK_EQ(MessageLoop::current(), message_loop_); | 125 DCHECK_EQ(MessageLoop::current(), message_loop_); |
143 base::AutoLock auto_lock(lock_); | 126 base::AutoLock auto_lock(lock_); |
144 frame_queue_available_.push_back(video_frame); | 127 CHECK(read_cb_.is_null()); |
| 128 read_cb_ = callback; |
145 } | 129 } |
146 | 130 |
147 gfx::Size RTCVideoDecoder::natural_size() { | 131 const gfx::Size& RTCVideoDecoder::natural_size() { |
148 // TODO(vrk): Return natural size when aspect ratio support is implemented. | 132 // TODO(vrk): Return natural size when aspect ratio support is implemented. |
149 return visible_size_; | 133 return visible_size_; |
150 } | 134 } |
151 | 135 |
152 bool RTCVideoDecoder::SetSize(int width, int height, int reserved) { | 136 bool RTCVideoDecoder::SetSize(int width, int height, int reserved) { |
153 visible_size_.SetSize(width, height); | 137 visible_size_.SetSize(width, height); |
154 | 138 |
155 // TODO(vrk): Provide natural size when aspect ratio support is implemented. | 139 // TODO(vrk): Provide natural size when aspect ratio support is implemented. |
156 host()->SetNaturalVideoSize(visible_size_); | 140 host()->SetNaturalVideoSize(visible_size_); |
157 return true; | 141 return true; |
158 } | 142 } |
159 | 143 |
160 bool RTCVideoDecoder::RenderFrame(const cricket::VideoFrame* frame) { | 144 bool RTCVideoDecoder::RenderFrame(const cricket::VideoFrame* frame) { |
| 145 // Called from libjingle thread. |
161 DCHECK(frame); | 146 DCHECK(frame); |
162 | 147 |
163 if (state_ != kNormal) | 148 if (state_ != kNormal) |
164 return true; | 149 return true; |
165 | 150 |
166 // This is called from another thread. | 151 ReadCB read_cb; |
167 scoped_refptr<VideoFrame> video_frame; | |
168 { | 152 { |
169 base::AutoLock auto_lock(lock_); | 153 base::AutoLock auto_lock(lock_); |
170 if (frame_queue_available_.size() == 0) { | 154 if (read_cb_.is_null()) { |
171 return true; | 155 return true; |
172 } | 156 } |
173 video_frame = frame_queue_available_.front(); | 157 std::swap(read_cb, read_cb_); |
174 frame_queue_available_.pop_front(); | |
175 } | 158 } |
176 | 159 |
177 // Check if there's a size change. | 160 // Always allocate a new frame. |
178 // TODO(vrk): Remove casts when media::VideoFrame is updated with gfx::Sizes | 161 // |
179 // for width/height. | 162 // TODO(scherkus): migrate this to proper buffer recycling. |
180 if (video_frame->width() != static_cast<size_t>(visible_size_.width()) || | 163 scoped_refptr<media::VideoFrame> video_frame = |
181 video_frame->height() != static_cast<size_t>(visible_size_.height())) { | 164 VideoFrame::CreateFrame(VideoFrame::YV12, |
182 // Allocate new buffer based on the new size. | 165 visible_size_.width(), |
183 video_frame = VideoFrame::CreateFrame(VideoFrame::YV12, | 166 visible_size_.height(), |
184 visible_size_.width(), | 167 host()->GetTime(), |
185 visible_size_.height(), | 168 base::TimeDelta::FromMilliseconds(30)); |
186 kNoTimestamp, | |
187 kNoTimestamp); | |
188 } | |
189 | 169 |
190 // Only YV12 frames are supported. | |
191 DCHECK(video_frame->format() == VideoFrame::YV12); | |
192 // Aspect ratio unsupported; DCHECK when there are non-square pixels. | 170 // Aspect ratio unsupported; DCHECK when there are non-square pixels. |
193 DCHECK(frame->GetPixelWidth() == 1); | 171 DCHECK_EQ(frame->GetPixelWidth(), 1u); |
194 DCHECK(frame->GetPixelHeight() == 1); | 172 DCHECK_EQ(frame->GetPixelHeight(), 1u); |
195 video_frame->SetTimestamp(host()->GetTime()); | |
196 video_frame->SetDuration(base::TimeDelta::FromMilliseconds(30)); | |
197 | 173 |
198 int y_rows = frame->GetHeight(); | 174 int y_rows = frame->GetHeight(); |
199 int uv_rows = frame->GetHeight() / 2; // YV12 format. | 175 int uv_rows = frame->GetHeight() / 2; // YV12 format. |
200 CopyYPlane(frame->GetYPlane(), frame->GetYPitch(), y_rows, video_frame); | 176 CopyYPlane(frame->GetYPlane(), frame->GetYPitch(), y_rows, video_frame); |
201 CopyUPlane(frame->GetUPlane(), frame->GetUPitch(), uv_rows, video_frame); | 177 CopyUPlane(frame->GetUPlane(), frame->GetUPitch(), uv_rows, video_frame); |
202 CopyVPlane(frame->GetVPlane(), frame->GetVPitch(), uv_rows, video_frame); | 178 CopyVPlane(frame->GetVPlane(), frame->GetVPitch(), uv_rows, video_frame); |
203 | 179 |
204 if (MessageLoop::current() != message_loop_) { | 180 read_cb.Run(video_frame); |
205 message_loop_->PostTask( | |
206 FROM_HERE, | |
207 base::Bind(&RTCVideoDecoder::VideoFrameReady, this, video_frame)); | |
208 } else { | |
209 VideoFrameReady(video_frame); | |
210 } | |
211 | |
212 return true; | 181 return true; |
213 } | 182 } |
OLD | NEW |