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

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

Issue 10749019: VideoDecodeAccelerator now SupportsWeakPtr instead of being RefCountedThreadSafe. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 5 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" 6 #include "base/command_line.h"
7 #include "base/debug/trace_event.h" 7 #include "base/debug/trace_event.h"
8 #include "base/logging.h" 8 #include "base/logging.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"
(...skipping 18 matching lines...) Expand all
29 using content::VaapiH264Decoder; 29 using content::VaapiH264Decoder;
30 30
31 VaapiVideoDecodeAccelerator::InputBuffer::InputBuffer() { 31 VaapiVideoDecodeAccelerator::InputBuffer::InputBuffer() {
32 } 32 }
33 33
34 VaapiVideoDecodeAccelerator::InputBuffer::~InputBuffer() { 34 VaapiVideoDecodeAccelerator::InputBuffer::~InputBuffer() {
35 } 35 }
36 36
37 void VaapiVideoDecodeAccelerator::NotifyError(Error error) { 37 void VaapiVideoDecodeAccelerator::NotifyError(Error error) {
38 if (message_loop_ != MessageLoop::current()) { 38 if (message_loop_ != MessageLoop::current()) {
39 DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
39 message_loop_->PostTask(FROM_HERE, base::Bind( 40 message_loop_->PostTask(FROM_HERE, base::Bind(
40 &VaapiVideoDecodeAccelerator::NotifyError, this, error)); 41 &VaapiVideoDecodeAccelerator::NotifyError, weak_this_, error));
41 return; 42 return;
42 } 43 }
43 44
44 DVLOG(1) << "Notifying of error " << error; 45 DVLOG(1) << "Notifying of error " << error;
45 46
46 if (client_) { 47 if (client_) {
47 client_->NotifyError(error); 48 client_->NotifyError(error);
48 client_ptr_factory_.InvalidateWeakPtrs(); 49 client_ptr_factory_.InvalidateWeakPtrs();
49 } 50 }
50 Destroy(); 51 Destroy(make_scoped_ptr<media::VideoDecodeAccelerator>(NULL));
51 } 52 }
52 53
53 VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator( 54 VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
54 Client* client, 55 Client* client,
55 const base::Callback<bool(void)>& make_context_current) 56 const base::Callback<bool(void)>& make_context_current)
56 : make_context_current_(make_context_current), 57 : make_context_current_(make_context_current),
57 state_(kUninitialized), 58 state_(kUninitialized),
58 input_ready_(&lock_), 59 input_ready_(&lock_),
59 output_ready_(&lock_), 60 output_ready_(&lock_),
60 message_loop_(MessageLoop::current()), 61 message_loop_(MessageLoop::current()),
62 weak_this_(base::AsWeakPtr(this)),
61 client_ptr_factory_(client), 63 client_ptr_factory_(client),
62 client_(client_ptr_factory_.GetWeakPtr()), 64 client_(client_ptr_factory_.GetWeakPtr()),
63 decoder_thread_("VaapiDecoderThread") { 65 decoder_thread_("VaapiDecoderThread") {
64 DCHECK(client); 66 DCHECK(client);
65 } 67 }
66 68
67 VaapiVideoDecodeAccelerator::~VaapiVideoDecodeAccelerator() { 69 VaapiVideoDecodeAccelerator::~VaapiVideoDecodeAccelerator() {
68 DCHECK_EQ(message_loop_, MessageLoop::current()); 70 DCHECK_EQ(message_loop_, MessageLoop::current());
69 } 71 }
70 72
71 bool VaapiVideoDecodeAccelerator::Initialize( 73 bool VaapiVideoDecodeAccelerator::Initialize(
72 media::VideoCodecProfile profile) { 74 media::VideoCodecProfile profile) {
73 DCHECK_EQ(message_loop_, MessageLoop::current()); 75 DCHECK_EQ(message_loop_, MessageLoop::current());
74 76
75 base::AutoLock auto_lock(lock_); 77 base::AutoLock auto_lock(lock_);
76 DCHECK_EQ(state_, kUninitialized); 78 DCHECK_EQ(state_, kUninitialized);
77 DVLOG(2) << "Initializing VAVDA, profile: " << profile; 79 DVLOG(2) << "Initializing VAVDA, profile: " << profile;
78 80
79 bool res = decoder_.Initialize( 81 bool res = decoder_.Initialize(
80 profile, x_display_, glx_context_, make_context_current_, 82 profile, x_display_, glx_context_, make_context_current_,
81 base::Bind(&VaapiVideoDecodeAccelerator::OutputPicCallback, this)); 83 base::Bind(&VaapiVideoDecodeAccelerator::OutputPicCallback,
84 base::Unretained(this)));
82 if (!res) { 85 if (!res) {
83 DVLOG(1) << "Failed initializing decoder"; 86 DVLOG(1) << "Failed initializing decoder";
84 return false; 87 return false;
85 } 88 }
86 89
87 CHECK(decoder_thread_.Start()); 90 CHECK(decoder_thread_.Start());
88 91
89 state_ = kInitialized; 92 state_ = kInitialized;
90 93
91 message_loop_->PostTask(FROM_HERE, base::Bind( 94 message_loop_->PostTask(FROM_HERE, base::Bind(
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 DVLOG(1) << "Requesting " << num_pics << " pictures of size: " 177 DVLOG(1) << "Requesting " << num_pics << " pictures of size: "
175 << size.width() << "x" << size.height(); 178 << size.width() << "x" << size.height();
176 message_loop_->PostTask(FROM_HERE, base::Bind( 179 message_loop_->PostTask(FROM_HERE, base::Bind(
177 &Client::ProvidePictureBuffers, client_, 180 &Client::ProvidePictureBuffers, client_,
178 num_pics, size, GL_TEXTURE_2D)); 181 num_pics, size, GL_TEXTURE_2D));
179 } else { 182 } else {
180 base::AutoLock auto_lock(lock_); 183 base::AutoLock auto_lock(lock_);
181 DCHECK_EQ(state_, kIdle); 184 DCHECK_EQ(state_, kIdle);
182 state_ = kDecoding; 185 state_ = kDecoding;
183 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( 186 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
184 &VaapiVideoDecodeAccelerator::DecodeTask, this)); 187 &VaapiVideoDecodeAccelerator::DecodeTask,
188 base::Unretained(this)));
185 } 189 }
186 return; 190 return;
187 191
188 case VaapiH264Decoder::kNeedMoreStreamData: 192 case VaapiH264Decoder::kNeedMoreStreamData:
189 ReturnCurrInputBuffer(); 193 ReturnCurrInputBuffer();
190 break; 194 break;
191 195
192 case VaapiH264Decoder::kDecodeError: 196 case VaapiH264Decoder::kDecodeError:
193 RETURN_AND_NOTIFY_ON_FAILURE(false, "Error in decoding", 197 RETURN_AND_NOTIFY_ON_FAILURE(false, "Error in decoding",
194 PLATFORM_FAILURE, ); 198 PLATFORM_FAILURE, );
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 TRACE_EVENT1("Video Decoder", "VAVDA::Decode", "Buffer id", 339 TRACE_EVENT1("Video Decoder", "VAVDA::Decode", "Buffer id",
336 bitstream_buffer.id()); 340 bitstream_buffer.id());
337 341
338 // We got a new input buffer from the client, map it and queue for later use. 342 // We got a new input buffer from the client, map it and queue for later use.
339 MapAndQueueNewInputBuffer(bitstream_buffer); 343 MapAndQueueNewInputBuffer(bitstream_buffer);
340 344
341 base::AutoLock auto_lock(lock_); 345 base::AutoLock auto_lock(lock_);
342 switch (state_) { 346 switch (state_) {
343 case kInitialized: 347 case kInitialized:
344 // Initial decode to get the required size of output buffers. 348 // Initial decode to get the required size of output buffers.
345 decoder_thread_.message_loop()->PostTask(FROM_HERE, 349 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
346 base::Bind(&VaapiVideoDecodeAccelerator::InitialDecodeTask, this)); 350 &VaapiVideoDecodeAccelerator::InitialDecodeTask,
351 base::Unretained(this)));
347 break; 352 break;
348 353
349 case kPicturesRequested: 354 case kPicturesRequested:
350 // Waiting for pictures, return. 355 // Waiting for pictures, return.
351 break; 356 break;
352 357
353 case kDecoding: 358 case kDecoding:
354 break; 359 break;
355 360
356 case kIdle: 361 case kIdle:
357 // Need to get decoder into suitable stream location to resume. 362 // Need to get decoder into suitable stream location to resume.
358 decoder_thread_.message_loop()->PostTask(FROM_HERE, 363 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
359 base::Bind(&VaapiVideoDecodeAccelerator::InitialDecodeTask, this)); 364 &VaapiVideoDecodeAccelerator::InitialDecodeTask,
365 base::Unretained(this)));
360 break; 366 break;
361 367
362 default: 368 default:
363 DVLOG(1) << "Decode request from client in invalid state: " << state_; 369 DVLOG(1) << "Decode request from client in invalid state: " << state_;
364 return; 370 return;
365 } 371 }
366 } 372 }
367 373
368 void VaapiVideoDecodeAccelerator::AssignPictureBuffers( 374 void VaapiVideoDecodeAccelerator::AssignPictureBuffers(
369 const std::vector<media::PictureBuffer>& buffers) { 375 const std::vector<media::PictureBuffer>& buffers) {
370 DCHECK_EQ(message_loop_, MessageLoop::current()); 376 DCHECK_EQ(message_loop_, MessageLoop::current());
371 377
372 base::AutoLock auto_lock(lock_); 378 base::AutoLock auto_lock(lock_);
373 DCHECK_EQ(state_, kPicturesRequested); 379 DCHECK_EQ(state_, kPicturesRequested);
374 380
375 for (size_t i = 0; i < buffers.size(); ++i) { 381 for (size_t i = 0; i < buffers.size(); ++i) {
376 DVLOG(2) << "Assigning picture id " << buffers[i].id() 382 DVLOG(2) << "Assigning picture id " << buffers[i].id()
377 << " to texture id " << buffers[i].texture_id(); 383 << " to texture id " << buffers[i].texture_id();
378 384
379 bool res = decoder_.AssignPictureBuffer(buffers[i].id(), 385 bool res = decoder_.AssignPictureBuffer(buffers[i].id(),
380 buffers[i].texture_id()); 386 buffers[i].texture_id());
381 RETURN_AND_NOTIFY_ON_FAILURE( 387 RETURN_AND_NOTIFY_ON_FAILURE(
382 res, "Failed assigning picture buffer id: " << buffers[i].id() << 388 res, "Failed assigning picture buffer id: " << buffers[i].id() <<
383 ", texture id: " << buffers[i].texture_id(), PLATFORM_FAILURE, ); 389 ", texture id: " << buffers[i].texture_id(), PLATFORM_FAILURE, );
384 } 390 }
385 391
386 state_ = kDecoding; 392 state_ = kDecoding;
387 decoder_thread_.message_loop()->PostTask(FROM_HERE, 393 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
388 base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask, this)); 394 &VaapiVideoDecodeAccelerator::DecodeTask, base::Unretained(this)));
389 } 395 }
390 396
391 void VaapiVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) { 397 void VaapiVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
392 DCHECK_EQ(message_loop_, MessageLoop::current()); 398 DCHECK_EQ(message_loop_, MessageLoop::current());
393 TRACE_EVENT1("Video Decoder", "VAVDA::ReusePictureBuffer", "Picture id", 399 TRACE_EVENT1("Video Decoder", "VAVDA::ReusePictureBuffer", "Picture id",
394 picture_buffer_id); 400 picture_buffer_id);
395 401
396 base::AutoLock auto_lock(lock_); 402 base::AutoLock auto_lock(lock_);
397 output_buffers_.push(picture_buffer_id); 403 output_buffers_.push(picture_buffer_id);
398 output_ready_.Signal(); 404 output_ready_.Signal();
399 } 405 }
400 406
401 void VaapiVideoDecodeAccelerator::FlushTask() { 407 void VaapiVideoDecodeAccelerator::FlushTask() {
402 DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current()); 408 DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
403 DVLOG(1) << "Flush task"; 409 DVLOG(1) << "Flush task";
404 410
405 // First flush all the pictures that haven't been outputted, notifying the 411 // First flush all the pictures that haven't been outputted, notifying the
406 // client to output them. 412 // client to output them.
407 bool res = decoder_.Flush(); 413 bool res = decoder_.Flush();
408 RETURN_AND_NOTIFY_ON_FAILURE(res, "Failed flushing the decoder.", 414 RETURN_AND_NOTIFY_ON_FAILURE(res, "Failed flushing the decoder.",
409 PLATFORM_FAILURE, ); 415 PLATFORM_FAILURE, );
410 416
411 // Put the decoder in idle state, ready to resume. 417 // Put the decoder in idle state, ready to resume.
412 decoder_.Reset(); 418 decoder_.Reset();
413 419
414 message_loop_->PostTask(FROM_HERE, 420 message_loop_->PostTask(FROM_HERE, base::Bind(
415 base::Bind(&VaapiVideoDecodeAccelerator::FinishFlush, this)); 421 &VaapiVideoDecodeAccelerator::FinishFlush, weak_this_));
416 } 422 }
417 423
418 void VaapiVideoDecodeAccelerator::Flush() { 424 void VaapiVideoDecodeAccelerator::Flush() {
419 DCHECK_EQ(message_loop_, MessageLoop::current()); 425 DCHECK_EQ(message_loop_, MessageLoop::current());
420 DVLOG(1) << "Got flush request"; 426 DVLOG(1) << "Got flush request";
421 427
422 base::AutoLock auto_lock(lock_); 428 base::AutoLock auto_lock(lock_);
423 state_ = kFlushing; 429 state_ = kFlushing;
424 // Queue a flush task after all existing decoding tasks to clean up. 430 // Queue a flush task after all existing decoding tasks to clean up.
425 decoder_thread_.message_loop()->PostTask(FROM_HERE, 431 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
426 base::Bind(&VaapiVideoDecodeAccelerator::FlushTask, this)); 432 &VaapiVideoDecodeAccelerator::FlushTask, base::Unretained(this)));
427 433
428 input_ready_.Signal(); 434 input_ready_.Signal();
429 output_ready_.Signal(); 435 output_ready_.Signal();
430 } 436 }
431 437
432 void VaapiVideoDecodeAccelerator::FinishFlush() { 438 void VaapiVideoDecodeAccelerator::FinishFlush() {
433 DCHECK_EQ(message_loop_, MessageLoop::current()); 439 DCHECK_EQ(message_loop_, MessageLoop::current());
434 440
435 base::AutoLock auto_lock(lock_); 441 base::AutoLock auto_lock(lock_);
436 if (state_ != kFlushing) { 442 if (state_ != kFlushing) {
(...skipping 16 matching lines...) Expand all
453 // by now, as this task was scheduled after them and client is expected not 459 // by now, as this task was scheduled after them and client is expected not
454 // to call Decode() after Reset() and before NotifyResetDone. 460 // to call Decode() after Reset() and before NotifyResetDone.
455 decoder_.Reset(); 461 decoder_.Reset();
456 462
457 // Return current input buffer, if present. 463 // Return current input buffer, if present.
458 if (curr_input_buffer_.get()) 464 if (curr_input_buffer_.get())
459 ReturnCurrInputBuffer(); 465 ReturnCurrInputBuffer();
460 466
461 // And let client know that we are done with reset. 467 // And let client know that we are done with reset.
462 message_loop_->PostTask(FROM_HERE, base::Bind( 468 message_loop_->PostTask(FROM_HERE, base::Bind(
463 &VaapiVideoDecodeAccelerator::FinishReset, this)); 469 &VaapiVideoDecodeAccelerator::FinishReset, weak_this_));
464 } 470 }
465 471
466 void VaapiVideoDecodeAccelerator::Reset() { 472 void VaapiVideoDecodeAccelerator::Reset() {
467 DCHECK_EQ(message_loop_, MessageLoop::current()); 473 DCHECK_EQ(message_loop_, MessageLoop::current());
468 DVLOG(1) << "Got reset request"; 474 DVLOG(1) << "Got reset request";
469 475
470 // This will make any new decode tasks exit early. 476 // This will make any new decode tasks exit early.
471 base::AutoLock auto_lock(lock_); 477 base::AutoLock auto_lock(lock_);
472 state_ = kResetting; 478 state_ = kResetting;
473 479
474 decoder_thread_.message_loop()->PostTask(FROM_HERE, 480 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
475 base::Bind(&VaapiVideoDecodeAccelerator::ResetTask, this)); 481 &VaapiVideoDecodeAccelerator::ResetTask, base::Unretained(this)));
476 482
477 input_ready_.Signal(); 483 input_ready_.Signal();
478 output_ready_.Signal(); 484 output_ready_.Signal();
479 } 485 }
480 486
481 void VaapiVideoDecodeAccelerator::FinishReset() { 487 void VaapiVideoDecodeAccelerator::FinishReset() {
482 DCHECK_EQ(message_loop_, MessageLoop::current()); 488 DCHECK_EQ(message_loop_, MessageLoop::current());
483 489
484 base::AutoLock auto_lock(lock_); 490 base::AutoLock auto_lock(lock_);
485 if (state_ != kResetting) { 491 if (state_ != kResetting) {
(...skipping 10 matching lines...) Expand all
496 } 502 }
497 503
498 state_ = kIdle; 504 state_ = kIdle;
499 505
500 message_loop_->PostTask(FROM_HERE, base::Bind( 506 message_loop_->PostTask(FROM_HERE, base::Bind(
501 &Client::NotifyResetDone, client_)); 507 &Client::NotifyResetDone, client_));
502 508
503 DVLOG(1) << "Reset finished"; 509 DVLOG(1) << "Reset finished";
504 } 510 }
505 511
506 void VaapiVideoDecodeAccelerator::Destroy() { 512 void VaapiVideoDecodeAccelerator::Destroy(
513 scoped_ptr<VideoDecodeAccelerator> self) {
507 DCHECK_EQ(message_loop_, MessageLoop::current()); 514 DCHECK_EQ(message_loop_, MessageLoop::current());
508 515
509 if (state_ == kUninitialized || state_ == kDestroying) 516 if (state_ == kUninitialized || state_ == kDestroying)
510 return; 517 return;
511 518
512 DVLOG(1) << "Destroying VAVDA"; 519 DVLOG(1) << "Destroying VAVDA";
513 base::AutoLock auto_lock(lock_); 520 base::AutoLock auto_lock(lock_);
514 state_ = kDestroying; 521 state_ = kDestroying;
515 522
516 client_ptr_factory_.InvalidateWeakPtrs(); 523 client_ptr_factory_.InvalidateWeakPtrs();
517 524
518 { 525 {
519 base::AutoUnlock auto_unlock(lock_); 526 base::AutoUnlock auto_unlock(lock_);
520 // Post a dummy task to the decoder_thread_ to ensure it is drained. 527 // Post a dummy task to the decoder_thread_ to ensure it is drained.
521 base::WaitableEvent waiter(false, false); 528 base::WaitableEvent waiter(false, false);
522 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( 529 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
523 &base::WaitableEvent::Signal, base::Unretained(&waiter))); 530 &base::WaitableEvent::Signal, base::Unretained(&waiter)));
524 input_ready_.Signal(); 531 input_ready_.Signal();
525 output_ready_.Signal(); 532 output_ready_.Signal();
526 waiter.Wait(); 533 waiter.Wait();
534 decoder_thread_.Stop();
527 } 535 }
528 536
529 decoder_.Destroy(); 537 decoder_.Destroy();
530 state_ = kUninitialized; 538 state_ = kUninitialized;
531 } 539 }
532 540
533 void VaapiVideoDecodeAccelerator::OutputPicCallback(int32 input_id, 541 void VaapiVideoDecodeAccelerator::OutputPicCallback(int32 input_id,
534 int32 output_id) { 542 int32 output_id) {
535 TRACE_EVENT2("Video Decoder", "VAVDA::OutputPicCallback", 543 TRACE_EVENT2("Video Decoder", "VAVDA::OutputPicCallback",
536 "Input id", input_id, "Picture id", output_id); 544 "Input id", input_id, "Picture id", output_id);
537 DVLOG(4) << "Outputting picture, input id: " << input_id 545 DVLOG(4) << "Outputting picture, input id: " << input_id
538 << " output id: " << output_id; 546 << " output id: " << output_id;
539 547
540 // Forward the request to the main thread. 548 // Forward the request to the main thread.
541 DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current()); 549 DCHECK_EQ(decoder_thread_.message_loop(), MessageLoop::current());
542 message_loop_->PostTask(FROM_HERE, 550 message_loop_->PostTask(FROM_HERE, base::Bind(
543 base::Bind(&VaapiVideoDecodeAccelerator::SyncAndNotifyPictureReady, 551 &VaapiVideoDecodeAccelerator::SyncAndNotifyPictureReady, weak_this_,
544 this, input_id, output_id)); 552 input_id, output_id));
545 } 553 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698