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

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

Powered by Google App Engine
This is Rietveld 408576698