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

Side by Side Diff: content/common/gpu/media/vaapi_video_decode_accelerator.cc

Issue 14914009: VAVDA: Redesign stage 1. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 months 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "base/bind.h" 5 #include "base/bind.h"
6 #include "base/command_line.h"
7 #include "base/debug/trace_event.h" 6 #include "base/debug/trace_event.h"
8 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/metrics/histogram.h"
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "base/string_util.h" 10 #include "base/string_util.h"
11 #include "base/synchronization/waitable_event.h" 11 #include "base/synchronization/waitable_event.h"
12 #include "gpu/command_buffer/service/gpu_switches.h"
13 #include "content/public/common/content_switches.h"
14 #include "content/common/gpu/gpu_channel.h" 12 #include "content/common/gpu/gpu_channel.h"
15 #include "content/common/gpu/media/vaapi_video_decode_accelerator.h" 13 #include "content/common/gpu/media/vaapi_video_decode_accelerator.h"
16 #include "media/base/bind_to_loop.h" 14 #include "media/base/bind_to_loop.h"
17 #include "media/video/picture.h" 15 #include "media/video/picture.h"
18 #include "third_party/libva/va/va.h"
19 #include "ui/gl/gl_bindings.h" 16 #include "ui/gl/gl_bindings.h"
17 #include "ui/gl/scoped_binders.h"
18
19 namespace {
Ami GONE FROM CHROMIUM 2013/05/17 23:19:15 pointless
Pawel Osciak 2013/05/21 22:32:35 Even if at some point a global ReportToUMA() surfa
Ami GONE FROM CHROMIUM 2013/05/22 23:59:47 Anything global in the future should be namespaced
Pawel Osciak 2013/05/24 01:46:39 Done.
20
21 static void ReportToUMA(
22 content::VaapiH264Decoder::VAVDAH264DecoderFailure failure) {
23 UMA_HISTOGRAM_ENUMERATION(
24 "Media.VAVDAH264.DecoderFailure",
Ami GONE FROM CHROMIUM 2013/05/17 23:19:15 This is clearly a decoder thing, not a VAVDA thing
Pawel Osciak 2013/05/21 22:32:35 Yeah, I hate it too, but didn't see a better way t
25 failure,
26 content::VaapiH264Decoder::VAVDA_H264_DECODER_FAILURES_MAX);
27 }
28
29 } // namespace
20 30
21 namespace content { 31 namespace content {
22 32
23 #define RETURN_AND_NOTIFY_ON_FAILURE(result, log, error_code, ret) \ 33 #define RETURN_AND_NOTIFY_ON_FAILURE(result, log, error_code, ret) \
24 do { \ 34 do { \
25 if (!(result)) { \ 35 if (!(result)) { \
26 DVLOG(1) << log; \ 36 DVLOG(1) << log; \
27 NotifyError(error_code); \ 37 NotifyError(error_code); \
28 return ret; \ 38 return ret; \
29 } \ 39 } \
(...skipping 17 matching lines...) Expand all
47 message_loop_->PostTask(FROM_HERE, base::Bind( 57 message_loop_->PostTask(FROM_HERE, base::Bind(
48 &VaapiVideoDecodeAccelerator::Cleanup, weak_this_)); 58 &VaapiVideoDecodeAccelerator::Cleanup, weak_this_));
49 59
50 DVLOG(1) << "Notifying of error " << error; 60 DVLOG(1) << "Notifying of error " << error;
51 if (client_) { 61 if (client_) {
52 client_->NotifyError(error); 62 client_->NotifyError(error);
53 client_ptr_factory_.InvalidateWeakPtrs(); 63 client_ptr_factory_.InvalidateWeakPtrs();
54 } 64 }
55 } 65 }
56 66
67 class VaapiVideoDecodeAccelerator::TFPPicture {
68 public:
69 ~TFPPicture();
70
71 static linked_ptr<TFPPicture> Create(
72 const base::Callback<bool(void)>& make_context_current,
73 const GLXFBConfig& fb_config,
74 Display* x_display,
75 int32 picture_buffer_id,
76 uint32 texture_id,
77 int width, int height);
78
79 int32 picture_buffer_id() {
Ami GONE FROM CHROMIUM 2013/05/17 23:19:15 Please rationalize order of ctor args, getters, an
Pawel Osciak 2013/05/21 22:32:35 Not really anything in particular, but getters are
80 return picture_buffer_id_;
81 }
82
83 uint32 texture_id() {
84 return texture_id_;
85 }
86
87 int width() {
88 return width_;
89 }
90
91 int height() {
92 return height_;
93 }
94
95 int x_pixmap() {
96 return x_pixmap_;
97 }
98
99 // Bind texture to pixmap. Needs to be called every frame.
100 bool Bind();
101
102 private:
103 TFPPicture(const base::Callback<bool(void)>& make_context_current,
104 Display* x_display,
105 int32 picture_buffer_id,
106 uint32 texture_id,
107 int width, int height);
108
109 bool Initialize(const GLXFBConfig& fb_config);
110
111 base::Callback<bool(void)> make_context_current_;
112
113 // Output id for the client.
114 int32 picture_buffer_id_;
115 uint32 texture_id_;
116
117 int width_;
118 int height_;
119
120 Display* x_display_;
121
122 // Pixmaps bound to this texture.
123 Pixmap x_pixmap_;
124 GLXPixmap glx_pixmap_;
125
126 DISALLOW_COPY_AND_ASSIGN(TFPPicture);
127 };
128
129 VaapiVideoDecodeAccelerator::TFPPicture::TFPPicture(
130 const base::Callback<bool(void)>& make_context_current,
131 Display* x_display,
132 int32 picture_buffer_id,
133 uint32 texture_id,
134 int width, int height)
135 : make_context_current_(make_context_current),
136 picture_buffer_id_(picture_buffer_id),
Ami GONE FROM CHROMIUM 2013/05/17 23:19:15 indent here and below
Pawel Osciak 2013/05/21 22:32:35 Done.
137 texture_id_(texture_id),
138 width_(width),
139 height_(height),
140 x_display_(x_display),
141 x_pixmap_(0),
142 glx_pixmap_(0) {
143 DCHECK(!make_context_current_.is_null());
144 };
145
146 linked_ptr<VaapiVideoDecodeAccelerator::TFPPicture>
147 VaapiVideoDecodeAccelerator::TFPPicture::Create(
148 const base::Callback<bool(void)>& make_context_current,
149 const GLXFBConfig& fb_config,
150 Display* x_display,
151 int32 picture_buffer_id,
152 uint32 texture_id,
153 int width, int height) {
154
155 linked_ptr<TFPPicture> tfp_picture(
156 new TFPPicture(make_context_current, x_display, picture_buffer_id,
157 texture_id, width, height));
158
159 if (!tfp_picture->Initialize(fb_config))
160 tfp_picture.reset();
161
162 return tfp_picture;
163 }
164
165 bool VaapiVideoDecodeAccelerator::TFPPicture::Initialize(
166 const GLXFBConfig& fb_config) {
167 if (!make_context_current_.Run())
168 return false;
169
170 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
171 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
172
173 XWindowAttributes win_attr;
174 int screen = DefaultScreen(x_display_);
175 XGetWindowAttributes(x_display_, RootWindow(x_display_, screen), &win_attr);
176 //TODO(posciak): pass the depth required by libva, not the RootWindow's depth
177 x_pixmap_ = XCreatePixmap(x_display_, RootWindow(x_display_, screen),
178 width_, height_, win_attr.depth);
179 if (!x_pixmap_) {
180 DVLOG(1) << "Failed creating an X Pixmap for TFP";
181 return NULL;
182 }
183
184 static const int pixmap_attr[] = {
185 GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
186 GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
187 GL_NONE,
188 };
189
190 glx_pixmap_ = glXCreatePixmap(x_display_, fb_config, x_pixmap_, pixmap_attr);
191 if (!glx_pixmap_) {
192 // x_pixmap_ will be freed in the destructor.
193 DVLOG(1) << "Failed creating a GLX Pixmap for TFP";
194 return NULL;
195 }
196
197 return true;
198 }
199
200 VaapiVideoDecodeAccelerator::TFPPicture::~TFPPicture() {
201 // Unbind surface from texture and deallocate resources.
202 if (glx_pixmap_ && make_context_current_.Run()) {
203 glXReleaseTexImageEXT(x_display_, glx_pixmap_, GLX_FRONT_LEFT_EXT);
204 glXDestroyPixmap(x_display_, glx_pixmap_);
205 }
206
207 if (x_pixmap_)
208 XFreePixmap(x_display_, x_pixmap_);
209 XSync(x_display_, False); // Needed to work around buggy vdpau-driver.
210 }
211
212 bool VaapiVideoDecodeAccelerator::TFPPicture::Bind() {
213 DCHECK(x_pixmap_);
214 DCHECK(glx_pixmap_);
215
216 if (!make_context_current_.Run())
217 return false;
218
219 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id_);
Ami GONE FROM CHROMIUM 2013/05/17 23:19:15 Is it really correct to have this be scoped to jus
Pawel Osciak 2013/05/21 22:32:35 No. This saves the texture that was bound (current
220 glXBindTexImageEXT(x_display_, glx_pixmap_, GLX_FRONT_LEFT_EXT, NULL);
221
222 return true;
223 }
224
225 VaapiVideoDecodeAccelerator::TFPPicture*
226 VaapiVideoDecodeAccelerator::TFPPictureById(int32 picture_buffer_id) {
227 TFPPictures::iterator it = tfp_pictures_.find(picture_buffer_id);
228 if (it == tfp_pictures_.end()) {
229 DVLOG(1) << "Picture id " << picture_buffer_id << " does not exist";
230 return NULL;
231 }
232
233 return it->second.get();
234 }
235
57 VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator( 236 VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
58 Display* x_display, GLXContext glx_context, 237 Display* x_display, GLXContext glx_context,
59 Client* client, 238 Client* client,
60 const base::Callback<bool(void)>& make_context_current) 239 const base::Callback<bool(void)>& make_context_current)
61 : x_display_(x_display), 240 : x_display_(x_display),
62 glx_context_(glx_context), 241 glx_context_(glx_context),
63 make_context_current_(make_context_current), 242 make_context_current_(make_context_current),
64 state_(kUninitialized), 243 state_(kUninitialized),
65 input_ready_(&lock_), 244 input_ready_(&lock_),
66 output_ready_(&lock_), 245 surfaces_available_(&lock_),
67 message_loop_(base::MessageLoop::current()), 246 message_loop_(base::MessageLoop::current()),
68 weak_this_(base::AsWeakPtr(this)), 247 weak_this_(base::AsWeakPtr(this)),
69 client_ptr_factory_(client), 248 client_ptr_factory_(client),
70 client_(client_ptr_factory_.GetWeakPtr()), 249 client_(client_ptr_factory_.GetWeakPtr()),
71 decoder_thread_("VaapiDecoderThread"), 250 decoder_thread_("VaapiDecoderThread"),
72 num_frames_at_client_(0), 251 num_frames_at_client_(0),
73 num_stream_bufs_at_decoder_(0) { 252 num_stream_bufs_at_decoder_(0) {
74 DCHECK(client); 253 DCHECK(client);
75 static bool vaapi_functions_initialized = PostSandboxInitialization();
76 RETURN_AND_NOTIFY_ON_FAILURE(vaapi_functions_initialized,
77 "Failed to initialize VAAPI libs",
78 PLATFORM_FAILURE, );
79 } 254 }
80 255
81 VaapiVideoDecodeAccelerator::~VaapiVideoDecodeAccelerator() { 256 VaapiVideoDecodeAccelerator::~VaapiVideoDecodeAccelerator() {
82 DCHECK_EQ(message_loop_, base::MessageLoop::current()); 257 DCHECK_EQ(message_loop_, base::MessageLoop::current());
83 } 258 }
84 259
260 class ScopedPtrXFree {
261 public:
262 void operator()(void* x) const {
263 ::XFree(x);
264 }
265 };
266
267 bool VaapiVideoDecodeAccelerator::InitializeFBConfig() {
268 const int fbconfig_attr[] = {
269 GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
270 GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
271 GLX_BIND_TO_TEXTURE_RGB_EXT, GL_TRUE,
272 GLX_Y_INVERTED_EXT, GL_TRUE,
273 GL_NONE,
274 };
275
276 int num_fbconfigs;
277 scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> glx_fb_configs(
278 glXChooseFBConfig(x_display_, DefaultScreen(x_display_), fbconfig_attr,
279 &num_fbconfigs));
280 if (!glx_fb_configs)
281 return false;
282 if (!num_fbconfigs)
283 return false;
284
285 fb_config_ = glx_fb_configs.get()[0];
286 return true;
287 }
288
85 bool VaapiVideoDecodeAccelerator::Initialize( 289 bool VaapiVideoDecodeAccelerator::Initialize(
86 media::VideoCodecProfile profile) { 290 media::VideoCodecProfile profile) {
87 DCHECK_EQ(message_loop_, base::MessageLoop::current()); 291 DCHECK_EQ(message_loop_, base::MessageLoop::current());
88 292
89 base::AutoLock auto_lock(lock_); 293 base::AutoLock auto_lock(lock_);
90 DCHECK_EQ(state_, kUninitialized); 294 DCHECK_EQ(state_, kUninitialized);
91 DVLOG(2) << "Initializing VAVDA, profile: " << profile; 295 DVLOG(2) << "Initializing VAVDA, profile: " << profile;
92 296
93 bool res = decoder_.Initialize( 297 if (!make_context_current_.Run())
94 profile, x_display_, glx_context_, make_context_current_, 298 return false;
95 media::BindToLoop(message_loop_->message_loop_proxy(), base::Bind( 299
96 &VaapiVideoDecodeAccelerator::NotifyPictureReady, weak_this_)), 300 if (!InitializeFBConfig()) {
97 media::BindToLoop(message_loop_->message_loop_proxy(), base::Bind( 301 DVLOG(1) << "Could not get a usable FBConfig";
98 &VaapiVideoDecodeAccelerator::SubmitDecode, weak_this_)));
99 if (!res) {
100 DVLOG(1) << "Failed initializing decoder";
101 return false; 302 return false;
102 } 303 }
103 304
305 vaapi_delegate_ = VaapiDelegate::Create(
306 profile, x_display_,
307 base::Bind(&ReportToUMA, content::VaapiH264Decoder::VAAPI_ERROR));
308
309 if (!vaapi_delegate_.get()) {
310 DVLOG(1) << "Failed initializing VAAPI";
311 return false;
312 }
313
314 decoder_.reset(
315 new VaapiH264Decoder(
316 vaapi_delegate_,
317 media::BindToLoop(message_loop_->message_loop_proxy(), base::Bind(
318 &VaapiVideoDecodeAccelerator::SurfaceReady, weak_this_)),
319 base::Bind(&ReportToUMA)));
320
104 CHECK(decoder_thread_.Start()); 321 CHECK(decoder_thread_.Start());
105 322
106 state_ = kInitialized; 323 state_ = kInitialized;
107 324
108 message_loop_->PostTask(FROM_HERE, base::Bind( 325 message_loop_->PostTask(FROM_HERE, base::Bind(
109 &Client::NotifyInitializeDone, client_)); 326 &Client::NotifyInitializeDone, client_));
110 return true; 327 return true;
111 } 328 }
112 329
113 void VaapiVideoDecodeAccelerator::SubmitDecode( 330 void VaapiVideoDecodeAccelerator::SyncSurfaceToPicture(
114 int32 output_id, 331 VASurfaceID va_surface_id,
115 scoped_ptr<std::queue<VABufferID> > va_bufs, 332 TFPPicture* tfp_picture) {
116 scoped_ptr<std::queue<VABufferID> > slice_bufs) {
117 DCHECK_EQ(message_loop_, base::MessageLoop::current()); 333 DCHECK_EQ(message_loop_, base::MessageLoop::current());
118 base::AutoLock auto_lock(lock_);
119 334
120 TRACE_EVENT1("Video Decoder", "VAVDA::Decode", "output_id", output_id); 335 RETURN_AND_NOTIFY_ON_FAILURE(tfp_picture->Bind(),
336 "Failed binding texture to pixmap",
337 PLATFORM_FAILURE, );
338
339 RETURN_AND_NOTIFY_ON_FAILURE(
340 vaapi_delegate_->PutSurfaceIntoPixmap(va_surface_id,
341 tfp_picture->x_pixmap(),
342 tfp_picture->width(),
343 tfp_picture->height()),
344 "Failed putting surface into pixmap", PLATFORM_FAILURE, );
345 }
346
347 void VaapiVideoDecodeAccelerator::SurfaceReady(
348 int32 input_id,
349 const scoped_refptr<VASurface>& va_surface) {
350 DCHECK_EQ(message_loop_, base::MessageLoop::current());
351
352 // Drop any requests to output if we are resetting.
353 if (state_ == kResetting || state_ == kDestroying)
354 return;
355
356 pending_output_cbs_.push(
357 base::Bind(&VaapiVideoDecodeAccelerator::OutputPicture,
358 weak_this_, va_surface, input_id));
359
360 TryOutputSurface();
361 }
362
363 void VaapiVideoDecodeAccelerator::OutputPicture(
364 const scoped_refptr<VASurface>& va_surface,
365 int32 input_id,
366 TFPPicture* tfp_picture) {
367 DCHECK_EQ(message_loop_, base::MessageLoop::current());
368
369 int32 output_id = tfp_picture->picture_buffer_id();
370
371 TRACE_EVENT2("Video Decoder", "VAVDA::OutputSurface",
372 "input_id", input_id,
373 "output_id", output_id);
374
375 DVLOG(3) << "Outputting VASurface " << va_surface->id()
376 << " into pixmap bound to picture buffer id " << output_id;
377
378 SyncSurfaceToPicture(va_surface->id(), tfp_picture);
379
380 // Notify the client a picture is ready to be displayed.
381 ++num_frames_at_client_;
382 TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_);
383 DVLOG(4) << "Notifying output picture id " << output_id
384 << " for input "<< input_id << " is ready";
385 client_->PictureReady(media::Picture(output_id, input_id));
386 }
387
388 void VaapiVideoDecodeAccelerator::TryOutputSurface() {
389 DCHECK_EQ(message_loop_, base::MessageLoop::current());
121 390
122 // Handle Destroy() arriving while pictures are queued for output. 391 // Handle Destroy() arriving while pictures are queued for output.
123 if (!client_) 392 if (!client_)
124 return; 393 return;
125 394
126 RETURN_AND_NOTIFY_ON_FAILURE( 395 if (pending_output_cbs_.empty() || output_buffers_.empty())
127 decoder_.SubmitDecode(output_id, va_bufs.Pass(), slice_bufs.Pass()),
128 "Failed putting picture to texture",
129 PLATFORM_FAILURE, );
130 }
131
132 void VaapiVideoDecodeAccelerator::NotifyPictureReady(int32 input_id,
133 int32 output_id) {
134 DCHECK_EQ(message_loop_, base::MessageLoop::current());
135 TRACE_EVENT2("Video Decoder", "VAVDA::NotifyPictureReady",
136 "input_id", input_id, "output_id", output_id);
137
138 // Handle Destroy() arriving while pictures are queued for output.
139 if (!client_)
140 return; 396 return;
141 397
142 // Don't return any pictures that we might want to return during resetting 398 OutputCB output_cb = pending_output_cbs_.front();
143 // as a consequence of finishing up the decode that was running during 399 pending_output_cbs_.pop();
144 // Reset() call from the client. Reuse it instead.
145 {
146 base::AutoLock auto_lock(lock_);
147 if (state_ == kResetting) {
148 output_buffers_.push(output_id);
149 return;
150 }
151 }
152 400
153 ++num_frames_at_client_; 401 TFPPicture* tfp_picture = TFPPictureById(output_buffers_.front());
154 TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_); 402 DCHECK(tfp_picture);
403 output_buffers_.pop();
155 404
156 // Notify the client a picture is ready to be displayed. 405 output_cb.Run(tfp_picture);
157 DVLOG(4) << "Notifying output picture id " << output_id
158 << " for input "<< input_id << " is ready";
159 client_->PictureReady(media::Picture(output_id, input_id));
160 } 406 }
161 407
162 void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer( 408 void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer(
163 const media::BitstreamBuffer& bitstream_buffer) { 409 const media::BitstreamBuffer& bitstream_buffer) {
164 DCHECK_EQ(message_loop_, base::MessageLoop::current()); 410 DCHECK_EQ(message_loop_, base::MessageLoop::current());
165 TRACE_EVENT1("Video Decoder", "MapAndQueueNewInputBuffer", "input_id", 411 TRACE_EVENT1("Video Decoder", "MapAndQueueNewInputBuffer", "input_id",
166 bitstream_buffer.id()); 412 bitstream_buffer.id());
167 413
168 DVLOG(4) << "Mapping new input buffer id: " << bitstream_buffer.id() 414 DVLOG(4) << "Mapping new input buffer id: " << bitstream_buffer.id()
169 << " size: " << (int)bitstream_buffer.size(); 415 << " size: " << (int)bitstream_buffer.size();
(...skipping 28 matching lines...) Expand all
198 DCHECK(curr_input_buffer_.get()); 444 DCHECK(curr_input_buffer_.get());
199 445
200 // Since multiple Decode()'s can be in flight at once, it's possible that a 446 // Since multiple Decode()'s can be in flight at once, it's possible that a
201 // Decode() that seemed like an initial one is actually later in the stream 447 // Decode() that seemed like an initial one is actually later in the stream
202 // and we're already kDecoding. Let the normal DecodeTask take over in that 448 // and we're already kDecoding. Let the normal DecodeTask take over in that
203 // case. 449 // case.
204 if (state_ != kInitialized && state_ != kIdle) 450 if (state_ != kInitialized && state_ != kIdle)
205 return; 451 return;
206 452
207 VaapiH264Decoder::DecResult res = 453 VaapiH264Decoder::DecResult res =
208 decoder_.DecodeInitial(curr_input_buffer_->id); 454 decoder_->DecodeInitial(curr_input_buffer_->id);
209 switch (res) { 455 switch (res) {
210 case VaapiH264Decoder::kReadyToDecode: 456 case VaapiH264Decoder::kReadyToDecode:
211 if (state_ == kInitialized) { 457 if (state_ == kInitialized) {
212 state_ = kPicturesRequested; 458 state_ = kPicturesRequested;
213 size_t num_pics = decoder_.GetRequiredNumOfPictures(); 459 num_pics_ = decoder_->GetRequiredNumOfPictures();
214 gfx::Size size(decoder_.pic_width(), decoder_.pic_height()); 460 pic_size_ = decoder_->GetPicSize();
215 DVLOG(1) << "Requesting " << num_pics << " pictures of size: " 461 DVLOG(1) << "Requesting " << num_pics_ << " pictures of size: "
216 << size.width() << "x" << size.height(); 462 << pic_size_.width() << "x" << pic_size_.height();
217 message_loop_->PostTask(FROM_HERE, base::Bind( 463 message_loop_->PostTask(FROM_HERE, base::Bind(
218 &Client::ProvidePictureBuffers, client_, 464 &Client::ProvidePictureBuffers, client_,
219 num_pics, size, GL_TEXTURE_2D)); 465 num_pics_, pic_size_, GL_TEXTURE_2D));
220 } else { 466 } else {
221 DCHECK_EQ(state_, kIdle); 467 DCHECK_EQ(state_, kIdle);
222 state_ = kDecoding; 468 state_ = kDecoding;
223 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( 469 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
224 &VaapiVideoDecodeAccelerator::DecodeTask, 470 &VaapiVideoDecodeAccelerator::DecodeTask,
225 base::Unretained(this))); 471 base::Unretained(this)));
226 } 472 }
227 return; 473 return;
228 474
229 case VaapiH264Decoder::kNeedMoreStreamData: 475 case VaapiH264Decoder::kNeedMoreStreamData:
230 ReturnCurrInputBuffer_Locked(); 476 ReturnCurrInputBuffer_Locked();
231 break; 477 break;
232 478
233 case VaapiH264Decoder::kNoOutputAvailable: 479 case VaapiH264Decoder::kNoOutputAvailable:
234 if (state_ == kIdle) { 480 if (state_ == kIdle) {
235 // No more output buffers in the decoder, try getting more or go to 481 // No more output buffers in the decoder, try getting more or go to
236 // sleep waiting for them. 482 // sleep waiting for them.
237 GetOutputBuffers_Locked(); 483 GetOutputSurfaces_Locked();
238 return; 484 return;
239 } 485 }
240 // else fallthrough 486 // else fallthrough
241 case VaapiH264Decoder::kDecodeError: 487 case VaapiH264Decoder::kDecodeError:
242 RETURN_AND_NOTIFY_ON_FAILURE(false, "Error in decoding", 488 RETURN_AND_NOTIFY_ON_FAILURE(false, "Error in decoding",
243 PLATFORM_FAILURE, ); 489 PLATFORM_FAILURE, );
244 490
245 default: 491 default:
246 RETURN_AND_NOTIFY_ON_FAILURE(false, 492 RETURN_AND_NOTIFY_ON_FAILURE(false,
247 "Unexpected result from decoder: " << res, 493 "Unexpected result from decoder: " << res,
(...skipping 30 matching lines...) Expand all
278 case kIdle: 524 case kIdle:
279 DCHECK(!input_buffers_.empty()); 525 DCHECK(!input_buffers_.empty());
280 526
281 curr_input_buffer_ = input_buffers_.front(); 527 curr_input_buffer_ = input_buffers_.front();
282 input_buffers_.pop(); 528 input_buffers_.pop();
283 529
284 DVLOG(4) << "New current bitstream buffer, id: " 530 DVLOG(4) << "New current bitstream buffer, id: "
285 << curr_input_buffer_->id 531 << curr_input_buffer_->id
286 << " size: " << curr_input_buffer_->size; 532 << " size: " << curr_input_buffer_->size;
287 533
288 decoder_.SetStream( 534 decoder_->SetStream(
289 static_cast<uint8*>(curr_input_buffer_->shm->memory()), 535 static_cast<uint8*>(curr_input_buffer_->shm->memory()),
290 curr_input_buffer_->size); 536 curr_input_buffer_->size);
291 return true; 537 return true;
292 538
293 default: 539 default:
294 // We got woken up due to being destroyed/reset, ignore any already 540 // We got woken up due to being destroyed/reset, ignore any already
295 // queued inputs. 541 // queued inputs.
296 return false; 542 return false;
297 } 543 }
298 } 544 }
299 545
300 void VaapiVideoDecodeAccelerator::ReturnCurrInputBuffer_Locked() { 546 void VaapiVideoDecodeAccelerator::ReturnCurrInputBuffer_Locked() {
301 lock_.AssertAcquired(); 547 lock_.AssertAcquired();
302 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 548 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
303 DCHECK(curr_input_buffer_.get()); 549 DCHECK(curr_input_buffer_.get());
304 550
305 int32 id = curr_input_buffer_->id; 551 int32 id = curr_input_buffer_->id;
306 curr_input_buffer_.reset(); 552 curr_input_buffer_.reset();
307 DVLOG(4) << "End of input buffer " << id; 553 DVLOG(4) << "End of input buffer " << id;
308 message_loop_->PostTask(FROM_HERE, base::Bind( 554 message_loop_->PostTask(FROM_HERE, base::Bind(
309 &Client::NotifyEndOfBitstreamBuffer, client_, id)); 555 &Client::NotifyEndOfBitstreamBuffer, client_, id));
310 556
311 --num_stream_bufs_at_decoder_; 557 --num_stream_bufs_at_decoder_;
312 TRACE_COUNTER1("Video Decoder", "Stream buffers at decoder", 558 TRACE_COUNTER1("Video Decoder", "Stream buffers at decoder",
313 num_stream_bufs_at_decoder_); 559 num_stream_bufs_at_decoder_);
314 } 560 }
315 561
316 bool VaapiVideoDecodeAccelerator::GetOutputBuffers_Locked() { 562 bool VaapiVideoDecodeAccelerator::GetOutputSurfaces_Locked() {
317 lock_.AssertAcquired(); 563 lock_.AssertAcquired();
318 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 564 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
319 565
320 while (output_buffers_.empty() && 566 while (available_va_surfaces_.empty() &&
321 (state_ == kDecoding || state_ == kFlushing || state_ == kIdle)) { 567 (state_ == kDecoding || state_ == kFlushing || state_ == kIdle)) {
322 output_ready_.Wait(); 568 surfaces_available_.Wait();
323 } 569 }
324 570
325 if (state_ != kDecoding && state_ != kFlushing && state_ != kIdle) 571 if (state_ != kDecoding && state_ != kFlushing && state_ != kIdle)
326 return false; 572 return false;
327 573
328 while (!output_buffers_.empty()) { 574 VASurface::ReleaseCB va_surface_relase_cb =
Ami GONE FROM CHROMIUM 2013/05/17 23:19:15 typo: va_surface_relase_cb
Pawel Osciak 2013/05/21 22:32:35 Done.
329 decoder_.ReusePictureBuffer(output_buffers_.front()); 575 media::BindToLoop(message_loop_->message_loop_proxy(), base::Bind(
330 output_buffers_.pop(); 576 &VaapiVideoDecodeAccelerator::RecycleVASurfaceID, weak_this_));
577
578 while (!available_va_surfaces_.empty()) {
579 scoped_refptr<VASurface> va_surface(
580 new VASurface(available_va_surfaces_.front(), va_surface_relase_cb));
581 available_va_surfaces_.pop_front();
582 decoder_->ReuseSurface(va_surface);
331 } 583 }
332 584
333 return true; 585 return true;
334 } 586 }
335 587
336 void VaapiVideoDecodeAccelerator::DecodeTask() { 588 void VaapiVideoDecodeAccelerator::DecodeTask() {
337 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 589 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
338 TRACE_EVENT0("Video Decoder", "VAVDA::DecodeTask"); 590 TRACE_EVENT0("Video Decoder", "VAVDA::DecodeTask");
339 base::AutoLock auto_lock(lock_); 591 base::AutoLock auto_lock(lock_);
340 592
341 // Main decode task. 593 // Main decode task.
342 DVLOG(4) << "Decode task"; 594 DVLOG(4) << "Decode task";
343 595
344 // Try to decode what stream data is (still) in the decoder until we run out 596 // Try to decode what stream data is (still) in the decoder until we run out
345 // of it. 597 // of it.
346 while (GetInputBuffer_Locked()) { 598 while (GetInputBuffer_Locked()) {
347 DCHECK(curr_input_buffer_.get()); 599 DCHECK(curr_input_buffer_.get());
348 600
349 VaapiH264Decoder::DecResult res; 601 VaapiH264Decoder::DecResult res;
350 res = decoder_.DecodeOneFrame(curr_input_buffer_->id); 602 {
603 base::AutoUnlock auto_unlock(lock_);
Ami GONE FROM CHROMIUM 2013/05/17 23:19:15 Comment about why and why safe.
Pawel Osciak 2013/05/21 22:32:35 Done.
604 res = decoder_->DecodeOneFrame(curr_input_buffer_->id);
605 }
351 606
352 switch (res) { 607 switch (res) {
353 case VaapiH264Decoder::kNeedMoreStreamData: 608 case VaapiH264Decoder::kNeedMoreStreamData:
354 ReturnCurrInputBuffer_Locked(); 609 ReturnCurrInputBuffer_Locked();
355 break; 610 break;
356 611
357 case VaapiH264Decoder::kDecodedFrame:
358 // May still have more stream data, continue decoding.
359 break;
360
361 case VaapiH264Decoder::kNoOutputAvailable: 612 case VaapiH264Decoder::kNoOutputAvailable:
362 // No more output buffers in the decoder, try getting more or go to 613 // No more output buffers in the decoder, try getting more or go to
363 // sleep waiting for them. 614 // sleep waiting for them.
364 if (!GetOutputBuffers_Locked()) 615 if (!GetOutputSurfaces_Locked())
365 return; 616 return;
366 break; 617 break;
367 618
368 case VaapiH264Decoder::kDecodeError: 619 case VaapiH264Decoder::kDecodeError:
369 RETURN_AND_NOTIFY_ON_FAILURE(false, "Error decoding stream", 620 RETURN_AND_NOTIFY_ON_FAILURE(false, "Error decoding stream",
370 PLATFORM_FAILURE, ); 621 PLATFORM_FAILURE, );
371 return; 622 return;
372 623
373 default: 624 default:
374 RETURN_AND_NOTIFY_ON_FAILURE( 625 RETURN_AND_NOTIFY_ON_FAILURE(
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 break; 667 break;
417 668
418 default: 669 default:
419 RETURN_AND_NOTIFY_ON_FAILURE(false, 670 RETURN_AND_NOTIFY_ON_FAILURE(false,
420 "Decode request from client in invalid state: " << state_, 671 "Decode request from client in invalid state: " << state_,
421 PLATFORM_FAILURE, ); 672 PLATFORM_FAILURE, );
422 return; 673 return;
423 } 674 }
424 } 675 }
425 676
677 void VaapiVideoDecodeAccelerator::RecycleVASurfaceID(
678 VASurfaceID va_surface_id) {
679 DCHECK_EQ(message_loop_, base::MessageLoop::current());
680
681 base::AutoLock auto_lock(lock_);
682
683 available_va_surfaces_.push_back(va_surface_id);
684 surfaces_available_.Signal();
685 }
686
426 void VaapiVideoDecodeAccelerator::AssignPictureBuffers( 687 void VaapiVideoDecodeAccelerator::AssignPictureBuffers(
427 const std::vector<media::PictureBuffer>& buffers) { 688 const std::vector<media::PictureBuffer>& buffers) {
428 DCHECK_EQ(message_loop_, base::MessageLoop::current()); 689 DCHECK_EQ(message_loop_, base::MessageLoop::current());
429 690
430 base::AutoLock auto_lock(lock_); 691 base::AutoLock auto_lock(lock_);
431 DCHECK_EQ(state_, kPicturesRequested); 692 DCHECK_EQ(state_, kPicturesRequested);
432 size_t num_pics = decoder_.GetRequiredNumOfPictures(); 693 DCHECK(tfp_pictures_.empty());
433 RETURN_AND_NOTIFY_ON_FAILURE((num_pics == buffers.size()), 694
434 "Failed to provide requested picture buffers. (Got " << buffers.size() << 695 RETURN_AND_NOTIFY_ON_FAILURE(
435 ", requested " << num_pics << ")", INVALID_ARGUMENT,); 696 buffers.size() == num_pics_,
697 "Got an invalid number of picture buffers. (Got " << buffers.size()
698 << ", requested " << num_pics_ << ")", INVALID_ARGUMENT, );
699
700 std::vector<VASurfaceID> va_surface_ids;
701 RETURN_AND_NOTIFY_ON_FAILURE(
702 vaapi_delegate_->CreateSurfaces(pic_size_.width(), pic_size_.height(),
703 buffers.size(),
704 va_surface_ids),
705 "Failed creating VA Surfaces", PLATFORM_FAILURE, );
706 DCHECK_EQ(va_surface_ids.size(), buffers.size());
436 707
437 for (size_t i = 0; i < buffers.size(); ++i) { 708 for (size_t i = 0; i < buffers.size(); ++i) {
438 DVLOG(2) << "Assigning picture id " << buffers[i].id() 709 DVLOG(2) << "Assigning picture id: " << buffers[i].id()
439 << " to texture id " << buffers[i].texture_id(); 710 << " to texture id: " << buffers[i].texture_id()
711 << " VASurfaceID: " << va_surface_ids[i];
440 712
441 bool res = decoder_.AssignPictureBuffer(buffers[i].id(), 713 linked_ptr<TFPPicture> tfp_picture(
442 buffers[i].texture_id()); 714 TFPPicture::Create(make_context_current_, fb_config_, x_display_,
715 buffers[i].id(), buffers[i].texture_id(),
716 pic_size_.width(), pic_size_.height()));
717
443 RETURN_AND_NOTIFY_ON_FAILURE( 718 RETURN_AND_NOTIFY_ON_FAILURE(
444 res, "Failed assigning picture buffer id: " << buffers[i].id() << 719 tfp_picture.get(), "Failed assigning picture buffer to a texture.",
445 ", texture id: " << buffers[i].texture_id(), PLATFORM_FAILURE, ); 720 PLATFORM_FAILURE, );
721
722 bool inserted = tfp_pictures_.insert(std::make_pair(
723 buffers[i].id(), tfp_picture)).second;
724 DCHECK(inserted);
725
726 output_buffers_.push(buffers[i].id());
727 available_va_surfaces_.push_back(va_surface_ids[i]);
728 surfaces_available_.Signal();
446 } 729 }
447 730
448 state_ = kDecoding; 731 state_ = kDecoding;
449 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( 732 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
450 &VaapiVideoDecodeAccelerator::DecodeTask, base::Unretained(this))); 733 &VaapiVideoDecodeAccelerator::DecodeTask, base::Unretained(this)));
451 } 734 }
452 735
453 void VaapiVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) { 736 void VaapiVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
454 DCHECK_EQ(message_loop_, base::MessageLoop::current()); 737 DCHECK_EQ(message_loop_, base::MessageLoop::current());
455 TRACE_EVENT1("Video Decoder", "VAVDA::ReusePictureBuffer", "Picture id", 738 TRACE_EVENT1("Video Decoder", "VAVDA::ReusePictureBuffer", "Picture id",
456 picture_buffer_id); 739 picture_buffer_id);
457 740
458 --num_frames_at_client_; 741 --num_frames_at_client_;
459 TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_); 742 TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_);
460 743
461 base::AutoLock auto_lock(lock_);
462 output_buffers_.push(picture_buffer_id); 744 output_buffers_.push(picture_buffer_id);
463 output_ready_.Signal(); 745 TryOutputSurface();
464 } 746 }
465 747
466 void VaapiVideoDecodeAccelerator::FlushTask() { 748 void VaapiVideoDecodeAccelerator::FlushTask() {
467 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 749 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
468 DVLOG(1) << "Flush task"; 750 DVLOG(1) << "Flush task";
469 751
470 base::AutoLock auto_lock(lock_);
471
472 // First flush all the pictures that haven't been outputted, notifying the 752 // First flush all the pictures that haven't been outputted, notifying the
473 // client to output them. 753 // client to output them.
474 bool res = decoder_.Flush(); 754 bool res = decoder_->Flush();
475 RETURN_AND_NOTIFY_ON_FAILURE(res, "Failed flushing the decoder.", 755 RETURN_AND_NOTIFY_ON_FAILURE(res, "Failed flushing the decoder.",
476 PLATFORM_FAILURE, ); 756 PLATFORM_FAILURE, );
477 757
478 // Put the decoder in idle state, ready to resume. 758 // Put the decoder in idle state, ready to resume.
479 decoder_.Reset(); 759 decoder_->Reset();
480 760
481 message_loop_->PostTask(FROM_HERE, base::Bind( 761 message_loop_->PostTask(FROM_HERE, base::Bind(
482 &VaapiVideoDecodeAccelerator::FinishFlush, weak_this_)); 762 &VaapiVideoDecodeAccelerator::FinishFlush, weak_this_));
483 } 763 }
484 764
485 void VaapiVideoDecodeAccelerator::Flush() { 765 void VaapiVideoDecodeAccelerator::Flush() {
486 DCHECK_EQ(message_loop_, base::MessageLoop::current()); 766 DCHECK_EQ(message_loop_, base::MessageLoop::current());
487 DVLOG(1) << "Got flush request"; 767 DVLOG(1) << "Got flush request";
488 768
489 base::AutoLock auto_lock(lock_); 769 base::AutoLock auto_lock(lock_);
490 state_ = kFlushing; 770 state_ = kFlushing;
491 // Queue a flush task after all existing decoding tasks to clean up. 771 // Queue a flush task after all existing decoding tasks to clean up.
492 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( 772 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
493 &VaapiVideoDecodeAccelerator::FlushTask, base::Unretained(this))); 773 &VaapiVideoDecodeAccelerator::FlushTask, base::Unretained(this)));
494 774
495 input_ready_.Signal(); 775 input_ready_.Signal();
496 output_ready_.Signal(); 776 surfaces_available_.Signal();
497 } 777 }
498 778
499 void VaapiVideoDecodeAccelerator::FinishFlush() { 779 void VaapiVideoDecodeAccelerator::FinishFlush() {
500 DCHECK_EQ(message_loop_, base::MessageLoop::current()); 780 DCHECK_EQ(message_loop_, base::MessageLoop::current());
501 781
502 base::AutoLock auto_lock(lock_); 782 base::AutoLock auto_lock(lock_);
503 if (state_ != kFlushing) { 783 if (state_ != kFlushing) {
504 DCHECK_EQ(state_, kDestroying); 784 DCHECK_EQ(state_, kDestroying);
505 return; // We could've gotten destroyed already. 785 return; // We could've gotten destroyed already.
506 } 786 }
507 787
508 state_ = kIdle; 788 state_ = kIdle;
509 789
510 message_loop_->PostTask(FROM_HERE, base::Bind( 790 message_loop_->PostTask(FROM_HERE, base::Bind(
511 &Client::NotifyFlushDone, client_)); 791 &Client::NotifyFlushDone, client_));
512 792
513 DVLOG(1) << "Flush finished"; 793 DVLOG(1) << "Flush finished";
514 } 794 }
515 795
516 void VaapiVideoDecodeAccelerator::ResetTask() { 796 void VaapiVideoDecodeAccelerator::ResetTask() {
517 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 797 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
518 798
519 base::AutoLock auto_lock(lock_);
520
521 // All the decoding tasks from before the reset request from client are done 799 // All the decoding tasks from before the reset request from client are done
522 // by now, as this task was scheduled after them and client is expected not 800 // by now, as this task was scheduled after them and client is expected not
523 // to call Decode() after Reset() and before NotifyResetDone. 801 // to call Decode() after Reset() and before NotifyResetDone.
524 decoder_.Reset(); 802 decoder_->Reset();
803
804 base::AutoLock auto_lock(lock_);
525 805
526 // Return current input buffer, if present. 806 // Return current input buffer, if present.
527 if (curr_input_buffer_.get()) 807 if (curr_input_buffer_.get())
528 ReturnCurrInputBuffer_Locked(); 808 ReturnCurrInputBuffer_Locked();
529 809
530 // And let client know that we are done with reset. 810 // And let client know that we are done with reset.
531 message_loop_->PostTask(FROM_HERE, base::Bind( 811 message_loop_->PostTask(FROM_HERE, base::Bind(
532 &VaapiVideoDecodeAccelerator::FinishReset, weak_this_)); 812 &VaapiVideoDecodeAccelerator::FinishReset, weak_this_));
533 } 813 }
534 814
(...skipping 10 matching lines...) Expand all
545 message_loop_->PostTask(FROM_HERE, base::Bind( 825 message_loop_->PostTask(FROM_HERE, base::Bind(
546 &Client::NotifyEndOfBitstreamBuffer, client_, 826 &Client::NotifyEndOfBitstreamBuffer, client_,
547 input_buffers_.front()->id)); 827 input_buffers_.front()->id));
548 input_buffers_.pop(); 828 input_buffers_.pop();
549 } 829 }
550 830
551 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( 831 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
552 &VaapiVideoDecodeAccelerator::ResetTask, base::Unretained(this))); 832 &VaapiVideoDecodeAccelerator::ResetTask, base::Unretained(this)));
553 833
554 input_ready_.Signal(); 834 input_ready_.Signal();
555 output_ready_.Signal(); 835 surfaces_available_.Signal();
556 } 836 }
557 837
558 void VaapiVideoDecodeAccelerator::FinishReset() { 838 void VaapiVideoDecodeAccelerator::FinishReset() {
559 DCHECK_EQ(message_loop_, base::MessageLoop::current()); 839 DCHECK_EQ(message_loop_, base::MessageLoop::current());
560 840
561 base::AutoLock auto_lock(lock_); 841 base::AutoLock auto_lock(lock_);
562 if (state_ != kResetting) { 842 if (state_ != kResetting) {
563 DCHECK(state_ == kDestroying || state_ == kUninitialized) << state_; 843 DCHECK(state_ == kDestroying || state_ == kUninitialized) << state_;
564 return; // We could've gotten destroyed already. 844 return; // We could've gotten destroyed already.
565 } 845 }
566 846
567 state_ = kIdle; 847 state_ = kIdle;
568 num_stream_bufs_at_decoder_ = 0; 848 num_stream_bufs_at_decoder_ = 0;
569 849
850 while(!pending_output_cbs_.empty())
851 pending_output_cbs_.pop();
852
570 message_loop_->PostTask(FROM_HERE, base::Bind( 853 message_loop_->PostTask(FROM_HERE, base::Bind(
571 &Client::NotifyResetDone, client_)); 854 &Client::NotifyResetDone, client_));
572 855
573 // The client might have given us new buffers via Decode() while we were 856 // The client might have given us new buffers via Decode() while we were
574 // resetting and might be waiting for our move, and not call Decode() anymore 857 // resetting and might be waiting for our move, and not call Decode() anymore
575 // until we return something. Post an InitialDecodeTask() so that we won't 858 // until we return something. Post an InitialDecodeTask() so that we won't
576 // sleep forever waiting for Decode() in that case. Having two of them 859 // sleep forever waiting for Decode() in that case. Having two of them
577 // in the pipe is harmless, the additional one will return as soon as it sees 860 // in the pipe is harmless, the additional one will return as soon as it sees
578 // that we are back in kDecoding state. 861 // that we are back in kDecoding state.
579 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( 862 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
(...skipping 15 matching lines...) Expand all
595 878
596 client_ptr_factory_.InvalidateWeakPtrs(); 879 client_ptr_factory_.InvalidateWeakPtrs();
597 880
598 { 881 {
599 base::AutoUnlock auto_unlock(lock_); 882 base::AutoUnlock auto_unlock(lock_);
600 // Post a dummy task to the decoder_thread_ to ensure it is drained. 883 // Post a dummy task to the decoder_thread_ to ensure it is drained.
601 base::WaitableEvent waiter(false, false); 884 base::WaitableEvent waiter(false, false);
602 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( 885 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
603 &base::WaitableEvent::Signal, base::Unretained(&waiter))); 886 &base::WaitableEvent::Signal, base::Unretained(&waiter)));
604 input_ready_.Signal(); 887 input_ready_.Signal();
605 output_ready_.Signal(); 888 surfaces_available_.Signal();
606 waiter.Wait(); 889 waiter.Wait();
607 decoder_thread_.Stop(); 890 decoder_thread_.Stop();
608 } 891 }
609 892
610 decoder_.Destroy();
611 state_ = kUninitialized; 893 state_ = kUninitialized;
612 } 894 }
613 895
614 void VaapiVideoDecodeAccelerator::Destroy() { 896 void VaapiVideoDecodeAccelerator::Destroy() {
615 DCHECK_EQ(message_loop_, base::MessageLoop::current()); 897 DCHECK_EQ(message_loop_, base::MessageLoop::current());
616 Cleanup(); 898 Cleanup();
617 delete this; 899 delete this;
618 } 900 }
619 901
620 // static
621 void VaapiVideoDecodeAccelerator::PreSandboxInitialization() {
622 VaapiH264Decoder::PreSandboxInitialization();
623 }
624
625 // static
626 bool VaapiVideoDecodeAccelerator::PostSandboxInitialization() {
627 return VaapiH264Decoder::PostSandboxInitialization();
628 }
629
630 } // namespace content 902 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698