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

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: fix for CaptureVideoDecoder 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"
11 #include "media/base/video_util.h" 11 #include "media/base/video_util.h"
12 12
13 using media::CopyYPlane; 13 using media::CopyYPlane;
14 using media::CopyUPlane; 14 using media::CopyUPlane;
15 using media::CopyVPlane; 15 using media::CopyVPlane;
16 16
17 CaptureVideoDecoder::CaptureVideoDecoder( 17 CaptureVideoDecoder::CaptureVideoDecoder(
18 base::MessageLoopProxy* message_loop_proxy, 18 base::MessageLoopProxy* message_loop_proxy,
19 media::VideoCaptureSessionId video_stream_id, 19 media::VideoCaptureSessionId video_stream_id,
20 VideoCaptureImplManager* vc_manager, 20 VideoCaptureImplManager* vc_manager,
21 const media::VideoCapture::VideoCaptureCapability& capability) 21 const media::VideoCapture::VideoCaptureCapability& capability)
22 : message_loop_proxy_(message_loop_proxy), 22 : message_loop_proxy_(message_loop_proxy),
23 vc_manager_(vc_manager), 23 vc_manager_(vc_manager),
24 capability_(capability), 24 capability_(capability),
25 natural_size_(capability.width, capability.height),
25 state_(kUnInitialized), 26 state_(kUnInitialized),
26 video_stream_id_(video_stream_id), 27 video_stream_id_(video_stream_id),
27 capture_engine_(NULL) { 28 capture_engine_(NULL) {
28 DCHECK(vc_manager); 29 DCHECK(vc_manager);
29 } 30 }
30 31
31 CaptureVideoDecoder::~CaptureVideoDecoder() {} 32 CaptureVideoDecoder::~CaptureVideoDecoder() {}
32 33
33 void CaptureVideoDecoder::Initialize( 34 void CaptureVideoDecoder::Initialize(
34 media::DemuxerStream* demuxer_stream, 35 media::DemuxerStream* demuxer_stream,
35 const base::Closure& filter_callback, 36 const base::Closure& filter_callback,
36 const media::StatisticsCallback& stat_callback) { 37 const media::StatisticsCallback& stat_callback) {
37 message_loop_proxy_->PostTask( 38 message_loop_proxy_->PostTask(
38 FROM_HERE, 39 FROM_HERE,
39 base::Bind(&CaptureVideoDecoder::InitializeOnDecoderThread, 40 base::Bind(&CaptureVideoDecoder::InitializeOnDecoderThread,
40 this, make_scoped_refptr(demuxer_stream), 41 this, make_scoped_refptr(demuxer_stream),
41 filter_callback, stat_callback)); 42 filter_callback, stat_callback));
42 } 43 }
43 44
44 void CaptureVideoDecoder::ProduceVideoFrame( 45 void CaptureVideoDecoder::Read(const ReadCB& callback) {
45 scoped_refptr<media::VideoFrame> video_frame) {
46 message_loop_proxy_->PostTask( 46 message_loop_proxy_->PostTask(
47 FROM_HERE, 47 FROM_HERE,
48 base::Bind(&CaptureVideoDecoder::ProduceVideoFrameOnDecoderThread, 48 base::Bind(&CaptureVideoDecoder::ReadOnDecoderThread,
49 this, video_frame)); 49 this, callback));
50 } 50 }
51 51
52 gfx::Size CaptureVideoDecoder::natural_size() { 52 const gfx::Size& CaptureVideoDecoder::natural_size() {
53 return gfx::Size(capability_.width, capability_.height); 53 return natural_size_;
54 } 54 }
55 55
56 void CaptureVideoDecoder::Play(const base::Closure& callback) { 56 void CaptureVideoDecoder::Play(const base::Closure& callback) {
57 message_loop_proxy_->PostTask( 57 message_loop_proxy_->PostTask(
58 FROM_HERE, 58 FROM_HERE,
59 base::Bind(&CaptureVideoDecoder::PlayOnDecoderThread, 59 base::Bind(&CaptureVideoDecoder::PlayOnDecoderThread,
60 this, callback)); 60 this, callback));
61 } 61 }
62 62
63 void CaptureVideoDecoder::Pause(const base::Closure& callback) { 63 void CaptureVideoDecoder::Pause(const base::Closure& callback) {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 124
125 void CaptureVideoDecoder::InitializeOnDecoderThread( 125 void CaptureVideoDecoder::InitializeOnDecoderThread(
126 media::DemuxerStream* demuxer_stream, 126 media::DemuxerStream* demuxer_stream,
127 const base::Closure& filter_callback, 127 const base::Closure& filter_callback,
128 const media::StatisticsCallback& stat_callback) { 128 const media::StatisticsCallback& stat_callback) {
129 VLOG(1) << "InitializeOnDecoderThread."; 129 VLOG(1) << "InitializeOnDecoderThread.";
130 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 130 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
131 131
132 capture_engine_ = vc_manager_->AddDevice(video_stream_id_, this); 132 capture_engine_ = vc_manager_->AddDevice(video_stream_id_, this);
133 133
134 available_frames_.clear();
135
136 statistics_callback_ = stat_callback; 134 statistics_callback_ = stat_callback;
137 filter_callback.Run(); 135 filter_callback.Run();
138 state_ = kNormal; 136 state_ = kNormal;
139 } 137 }
140 138
141 void CaptureVideoDecoder::ProduceVideoFrameOnDecoderThread( 139 void CaptureVideoDecoder::ReadOnDecoderThread(const ReadCB& callback) {
142 scoped_refptr<media::VideoFrame> video_frame) {
143 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 140 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
144 available_frames_.push_back(video_frame); 141 CHECK(read_cb_.is_null());
142 read_cb_ = callback;
145 } 143 }
146 144
147 void CaptureVideoDecoder::PlayOnDecoderThread(const base::Closure& callback) { 145 void CaptureVideoDecoder::PlayOnDecoderThread(const base::Closure& callback) {
148 VLOG(1) << "PlayOnDecoderThread."; 146 VLOG(1) << "PlayOnDecoderThread.";
149 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 147 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
150 callback.Run(); 148 callback.Run();
151 } 149 }
152 150
153 void CaptureVideoDecoder::PauseOnDecoderThread(const base::Closure& callback) { 151 void CaptureVideoDecoder::PauseOnDecoderThread(const base::Closure& callback) {
154 VLOG(1) << "PauseOnDecoderThread."; 152 VLOG(1) << "PauseOnDecoderThread.";
155 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 153 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
156 state_ = kPaused; 154 state_ = kPaused;
157 media::VideoDecoder::Pause(callback); 155 media::VideoDecoder::Pause(callback);
158 } 156 }
159 157
160 void CaptureVideoDecoder::StopOnDecoderThread(const base::Closure& callback) { 158 void CaptureVideoDecoder::StopOnDecoderThread(const base::Closure& callback) {
161 VLOG(1) << "StopOnDecoderThread."; 159 VLOG(1) << "StopOnDecoderThread.";
162 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 160 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
163 pending_stop_cb_ = callback; 161 pending_stop_cb_ = callback;
164 state_ = kStopped; 162 state_ = kStopped;
165 capture_engine_->StopCapture(this); 163 capture_engine_->StopCapture(this);
166 } 164 }
167 165
168 void CaptureVideoDecoder::SeekOnDecoderThread(base::TimeDelta time, 166 void CaptureVideoDecoder::SeekOnDecoderThread(base::TimeDelta time,
169 const media::FilterStatusCB& cb) { 167 const media::FilterStatusCB& cb) {
170 VLOG(1) << "SeekOnDecoderThread."; 168 VLOG(1) << "SeekOnDecoderThread.";
171 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 169 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
172 170
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); 171 cb.Run(media::PIPELINE_OK);
182 state_ = kNormal; 172 state_ = kNormal;
183 capture_engine_->StartCapture(this, capability_); 173 capture_engine_->StartCapture(this, capability_);
184 } 174 }
185 175
186 void CaptureVideoDecoder::OnStoppedOnDecoderThread( 176 void CaptureVideoDecoder::OnStoppedOnDecoderThread(
187 media::VideoCapture* capture) { 177 media::VideoCapture* capture) {
188 VLOG(1) << "OnStoppedOnDecoderThread."; 178 VLOG(1) << "OnStoppedOnDecoderThread.";
189 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 179 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
190 if (!pending_stop_cb_.is_null()) 180 if (!pending_stop_cb_.is_null())
191 media::ResetAndRunCB(&pending_stop_cb_); 181 media::ResetAndRunCB(&pending_stop_cb_);
192 vc_manager_->RemoveDevice(video_stream_id_, this); 182 vc_manager_->RemoveDevice(video_stream_id_, this);
193 } 183 }
194 184
195 void CaptureVideoDecoder::OnBufferReadyOnDecoderThread( 185 void CaptureVideoDecoder::OnBufferReadyOnDecoderThread(
196 media::VideoCapture* capture, 186 media::VideoCapture* capture,
197 scoped_refptr<media::VideoCapture::VideoFrameBuffer> buf) { 187 scoped_refptr<media::VideoCapture::VideoFrameBuffer> buf) {
198 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 188 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
199 189
200 if (available_frames_.size() == 0 || kNormal != state_) { 190 if (read_cb_.is_null() || kNormal != state_) {
201 capture->FeedBuffer(buf); 191 capture->FeedBuffer(buf);
202 return; 192 return;
203 } 193 }
204 194
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) { 195 if (buf->width != capability_.width || buf->height != capability_.height) {
209 capability_.width = buf->width; 196 capability_.width = buf->width;
210 capability_.height = buf->height; 197 capability_.height = buf->height;
211 host()->SetNaturalVideoSize( 198 natural_size_.SetSize(buf->width, buf->height);
212 gfx::Size(capability_.width, capability_.height)); 199 host()->SetNaturalVideoSize(natural_size_);
213 } 200 }
214 201
215 // Check if there's a size change. 202 // Always allocate a new frame.
216 if (static_cast<int>(video_frame->width()) != capability_.width || 203 //
217 static_cast<int>(video_frame->height()) != capability_.height) { 204 // TODO(scherkus): migrate this to proper buffer recycling.
218 // Allocate new buffer based on the new size. 205 scoped_refptr<media::VideoFrame> video_frame =
219 video_frame = media::VideoFrame::CreateFrame(media::VideoFrame::YV12, 206 media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
220 capability_.width, 207 natural_size_.width(),
221 capability_.height, 208 natural_size_.height(),
222 media::kNoTimestamp, 209 buf->timestamp - start_time_,
223 media::kNoTimestamp); 210 base::TimeDelta::FromMilliseconds(33));
224 }
225
226 video_frame->SetTimestamp(buf->timestamp - start_time_);
227 video_frame->SetDuration(base::TimeDelta::FromMilliseconds(33));
228 211
229 uint8* buffer = buf->memory_pointer; 212 uint8* buffer = buf->memory_pointer;
230 213
231 // Assume YV12 format. 214 // Assume YV12 format.
232 // TODO(vrk): This DCHECK fails in content_unittests ... it should not! 215 // TODO(vrk): This DCHECK fails in content_unittests ... it should not!
233 // DCHECK(capability_.raw_type == media::VideoFrame::YV12); 216 // DCHECK(capability_.raw_type == media::VideoFrame::YV12);
234 int y_width = capability_.width; 217 int y_width = capability_.width;
235 int y_height = capability_.height; 218 int y_height = capability_.height;
236 int uv_width = capability_.width / 2; 219 int uv_width = capability_.width / 2;
237 int uv_height = capability_.height / 2; // YV12 format. 220 int uv_height = capability_.height / 2; // YV12 format.
238 CopyYPlane(buffer, y_width, y_height, video_frame); 221 CopyYPlane(buffer, y_width, y_height, video_frame);
239 buffer += y_width * y_height; 222 buffer += y_width * y_height;
240 CopyUPlane(buffer, uv_width, uv_height, video_frame); 223 CopyUPlane(buffer, uv_width, uv_height, video_frame);
241 buffer += uv_width * uv_height; 224 buffer += uv_width * uv_height;
242 CopyVPlane(buffer, uv_width, uv_height, video_frame); 225 CopyVPlane(buffer, uv_width, uv_height, video_frame);
243 226
244 VideoFrameReady(video_frame); 227 DeliverFrame(video_frame);
245 capture->FeedBuffer(buf); 228 capture->FeedBuffer(buf);
246 } 229 }
230
231 void CaptureVideoDecoder::DeliverFrame(
232 const scoped_refptr<media::VideoFrame>& video_frame) {
233 // Reset the callback before running to protect against reentrancy.
234 ReadCB read_cb = read_cb_;
235 read_cb_.Reset();
236 read_cb.Run(video_frame);
237 }
OLDNEW
« no previous file with comments | « content/renderer/media/capture_video_decoder.h ('k') | content/renderer/media/capture_video_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698