Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(427)

Side by Side Diff: content/renderer/media/capture_video_decoder.cc

Issue 8417019: Simplify VideoDecodeEngine interface by making everything synchronous. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixes Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/capture_video_decoder.h" 5 #include "content/renderer/media/capture_video_decoder.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "content/renderer/media/video_capture_impl_manager.h" 8 #include "content/renderer/media/video_capture_impl_manager.h"
9 #include "media/base/filter_host.h" 9 #include "media/base/filter_host.h"
10 #include "media/base/limits.h" 10 #include "media/base/limits.h"
(...skipping 23 matching lines...) Expand all
34 media::DemuxerStream* demuxer_stream, 34 media::DemuxerStream* demuxer_stream,
35 const base::Closure& filter_callback, 35 const base::Closure& filter_callback,
36 const media::StatisticsCallback& stat_callback) { 36 const media::StatisticsCallback& stat_callback) {
37 message_loop_proxy_->PostTask( 37 message_loop_proxy_->PostTask(
38 FROM_HERE, 38 FROM_HERE,
39 base::Bind(&CaptureVideoDecoder::InitializeOnDecoderThread, 39 base::Bind(&CaptureVideoDecoder::InitializeOnDecoderThread,
40 this, make_scoped_refptr(demuxer_stream), 40 this, make_scoped_refptr(demuxer_stream),
41 filter_callback, stat_callback)); 41 filter_callback, stat_callback));
42 } 42 }
43 43
44 void CaptureVideoDecoder::ProduceVideoFrame( 44 void CaptureVideoDecoder::Read(const ReadCB& callback) {
45 scoped_refptr<media::VideoFrame> video_frame) {
46 message_loop_proxy_->PostTask( 45 message_loop_proxy_->PostTask(
47 FROM_HERE, 46 FROM_HERE,
48 base::Bind(&CaptureVideoDecoder::ProduceVideoFrameOnDecoderThread, 47 base::Bind(&CaptureVideoDecoder::ReadOnDecoderThread,
49 this, video_frame)); 48 this, callback));
50 } 49 }
51 50
52 gfx::Size CaptureVideoDecoder::natural_size() { 51 gfx::Size CaptureVideoDecoder::natural_size() {
53 return gfx::Size(capability_.width, capability_.height); 52 return gfx::Size(capability_.width, capability_.height);
54 } 53 }
55 54
56 void CaptureVideoDecoder::Play(const base::Closure& callback) { 55 void CaptureVideoDecoder::Play(const base::Closure& callback) {
57 message_loop_proxy_->PostTask( 56 message_loop_proxy_->PostTask(
58 FROM_HERE, 57 FROM_HERE,
59 base::Bind(&CaptureVideoDecoder::PlayOnDecoderThread, 58 base::Bind(&CaptureVideoDecoder::PlayOnDecoderThread,
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 123
125 void CaptureVideoDecoder::InitializeOnDecoderThread( 124 void CaptureVideoDecoder::InitializeOnDecoderThread(
126 media::DemuxerStream* demuxer_stream, 125 media::DemuxerStream* demuxer_stream,
127 const base::Closure& filter_callback, 126 const base::Closure& filter_callback,
128 const media::StatisticsCallback& stat_callback) { 127 const media::StatisticsCallback& stat_callback) {
129 VLOG(1) << "InitializeOnDecoderThread."; 128 VLOG(1) << "InitializeOnDecoderThread.";
130 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 129 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
131 130
132 capture_engine_ = vc_manager_->AddDevice(video_stream_id_, this); 131 capture_engine_ = vc_manager_->AddDevice(video_stream_id_, this);
133 132
134 available_frames_.clear();
135
136 statistics_callback_ = stat_callback; 133 statistics_callback_ = stat_callback;
137 filter_callback.Run(); 134 filter_callback.Run();
138 state_ = kNormal; 135 state_ = kNormal;
139 } 136 }
140 137
141 void CaptureVideoDecoder::ProduceVideoFrameOnDecoderThread( 138 void CaptureVideoDecoder::ReadOnDecoderThread(const ReadCB& callback) {
142 scoped_refptr<media::VideoFrame> video_frame) {
143 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 139 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
144 available_frames_.push_back(video_frame); 140 CHECK(read_cb_.is_null());
141 read_cb_ = callback;
145 } 142 }
146 143
147 void CaptureVideoDecoder::PlayOnDecoderThread(const base::Closure& callback) { 144 void CaptureVideoDecoder::PlayOnDecoderThread(const base::Closure& callback) {
148 VLOG(1) << "PlayOnDecoderThread."; 145 VLOG(1) << "PlayOnDecoderThread.";
149 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 146 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
150 callback.Run(); 147 callback.Run();
151 } 148 }
152 149
153 void CaptureVideoDecoder::PauseOnDecoderThread(const base::Closure& callback) { 150 void CaptureVideoDecoder::PauseOnDecoderThread(const base::Closure& callback) {
154 VLOG(1) << "PauseOnDecoderThread."; 151 VLOG(1) << "PauseOnDecoderThread.";
155 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 152 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
156 state_ = kPaused; 153 state_ = kPaused;
157 media::VideoDecoder::Pause(callback); 154 media::VideoDecoder::Pause(callback);
158 } 155 }
159 156
160 void CaptureVideoDecoder::StopOnDecoderThread(const base::Closure& callback) { 157 void CaptureVideoDecoder::StopOnDecoderThread(const base::Closure& callback) {
161 VLOG(1) << "StopOnDecoderThread."; 158 VLOG(1) << "StopOnDecoderThread.";
162 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 159 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
163 pending_stop_cb_ = callback; 160 pending_stop_cb_ = callback;
164 state_ = kStopped; 161 state_ = kStopped;
165 capture_engine_->StopCapture(this); 162 capture_engine_->StopCapture(this);
166 } 163 }
167 164
168 void CaptureVideoDecoder::SeekOnDecoderThread(base::TimeDelta time, 165 void CaptureVideoDecoder::SeekOnDecoderThread(base::TimeDelta time,
169 const media::FilterStatusCB& cb) { 166 const media::FilterStatusCB& cb) {
170 VLOG(1) << "SeekOnDecoderThread."; 167 VLOG(1) << "SeekOnDecoderThread.";
171 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 168 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
172 169
173 state_ = kSeeking;
174 // Create output buffer pool and pass the frames to renderer
175 // so that the renderer can complete the seeking
176 for (size_t i = 0; i < media::Limits::kMaxVideoFrames; ++i) {
177 VideoFrameReady(media::VideoFrame::CreateBlackFrame(capability_.width,
178 capability_.height));
179 }
180
181 cb.Run(media::PIPELINE_OK); 170 cb.Run(media::PIPELINE_OK);
182 state_ = kNormal; 171 state_ = kNormal;
183 capture_engine_->StartCapture(this, capability_); 172 capture_engine_->StartCapture(this, capability_);
184 } 173 }
185 174
186 void CaptureVideoDecoder::OnStoppedOnDecoderThread( 175 void CaptureVideoDecoder::OnStoppedOnDecoderThread(
187 media::VideoCapture* capture) { 176 media::VideoCapture* capture) {
188 VLOG(1) << "OnStoppedOnDecoderThread."; 177 VLOG(1) << "OnStoppedOnDecoderThread.";
189 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 178 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
190 if (!pending_stop_cb_.is_null()) 179 if (!pending_stop_cb_.is_null())
191 media::ResetAndRunCB(&pending_stop_cb_); 180 media::ResetAndRunCB(&pending_stop_cb_);
192 vc_manager_->RemoveDevice(video_stream_id_, this); 181 vc_manager_->RemoveDevice(video_stream_id_, this);
193 } 182 }
194 183
195 void CaptureVideoDecoder::OnBufferReadyOnDecoderThread( 184 void CaptureVideoDecoder::OnBufferReadyOnDecoderThread(
196 media::VideoCapture* capture, 185 media::VideoCapture* capture,
197 scoped_refptr<media::VideoCapture::VideoFrameBuffer> buf) { 186 scoped_refptr<media::VideoCapture::VideoFrameBuffer> buf) {
198 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 187 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
199 188
200 if (available_frames_.size() == 0 || kNormal != state_) { 189 if (read_cb_.is_null() || kNormal != state_) {
201 capture->FeedBuffer(buf); 190 capture->FeedBuffer(buf);
202 return; 191 return;
203 } 192 }
204 193
205 scoped_refptr<media::VideoFrame> video_frame = available_frames_.front();
206 available_frames_.pop_front();
207
208 if (buf->width != capability_.width || buf->height != capability_.height) { 194 if (buf->width != capability_.width || buf->height != capability_.height) {
209 capability_.width = buf->width; 195 capability_.width = buf->width;
210 capability_.height = buf->height; 196 capability_.height = buf->height;
211 host()->SetNaturalVideoSize( 197 host()->SetNaturalVideoSize(
212 gfx::Size(capability_.width, capability_.height)); 198 gfx::Size(capability_.width, capability_.height));
213 } 199 }
214 200
215 // Check if there's a size change. 201 // Always allocate a new frame.
216 if (static_cast<int>(video_frame->width()) != capability_.width || 202 //
217 static_cast<int>(video_frame->height()) != capability_.height) { 203 // TODO(scherkus): migrate this to proper buffer recycling.
218 // Allocate new buffer based on the new size. 204 scoped_refptr<media::VideoFrame> video_frame =
219 video_frame = media::VideoFrame::CreateFrame(media::VideoFrame::YV12, 205 media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
220 capability_.width, 206 capability_.width,
221 capability_.height, 207 capability_.height,
222 media::kNoTimestamp, 208 buf->timestamp - start_time_,
223 media::kNoTimestamp); 209 base::TimeDelta::FromMilliseconds(33));
224 }
225
226 video_frame->SetTimestamp(buf->timestamp - start_time_);
227 video_frame->SetDuration(base::TimeDelta::FromMilliseconds(33));
228 210
229 uint8* buffer = buf->memory_pointer; 211 uint8* buffer = buf->memory_pointer;
230 212
231 // Assume YV12 format. 213 // Assume YV12 format.
232 // TODO(vrk): This DCHECK fails in content_unittests ... it should not! 214 // TODO(vrk): This DCHECK fails in content_unittests ... it should not!
233 // DCHECK(capability_.raw_type == media::VideoFrame::YV12); 215 // DCHECK(capability_.raw_type == media::VideoFrame::YV12);
234 int y_width = capability_.width; 216 int y_width = capability_.width;
235 int y_height = capability_.height; 217 int y_height = capability_.height;
236 int uv_width = capability_.width / 2; 218 int uv_width = capability_.width / 2;
237 int uv_height = capability_.height / 2; // YV12 format. 219 int uv_height = capability_.height / 2; // YV12 format.
238 CopyYPlane(buffer, y_width, y_height, video_frame); 220 CopyYPlane(buffer, y_width, y_height, video_frame);
239 buffer += y_width * y_height; 221 buffer += y_width * y_height;
240 CopyUPlane(buffer, uv_width, uv_height, video_frame); 222 CopyUPlane(buffer, uv_width, uv_height, video_frame);
241 buffer += uv_width * uv_height; 223 buffer += uv_width * uv_height;
242 CopyVPlane(buffer, uv_width, uv_height, video_frame); 224 CopyVPlane(buffer, uv_width, uv_height, video_frame);
243 225
244 VideoFrameReady(video_frame); 226 DeliverFrame(video_frame);
245 capture->FeedBuffer(buf); 227 capture->FeedBuffer(buf);
246 } 228 }
229
230 void CaptureVideoDecoder::DeliverFrame(
231 const scoped_refptr<media::VideoFrame>& video_frame) {
232 // Reset the callback before running to protect against reentrancy.
233 ReadCB read_cb = read_cb_;
234 read_cb_.Reset();
235 read_cb.Run(video_frame);
236 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698