OLD | NEW |
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 "media/gpu/vaapi_video_decode_accelerator.h" | 5 #include "media/gpu/vaapi_video_decode_accelerator.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/files/scoped_file.h" | 12 #include "base/files/scoped_file.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/macros.h" | 14 #include "base/macros.h" |
15 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
16 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
17 #include "base/strings/string_util.h" | 17 #include "base/strings/string_util.h" |
18 #include "base/synchronization/waitable_event.h" | 18 #include "base/synchronization/waitable_event.h" |
| 19 #include "base/threading/thread_task_runner_handle.h" |
19 #include "base/trace_event/trace_event.h" | 20 #include "base/trace_event/trace_event.h" |
20 #include "gpu/ipc/service/gpu_channel.h" | 21 #include "gpu/ipc/service/gpu_channel.h" |
21 #include "media/base/bind_to_current_loop.h" | 22 #include "media/base/bind_to_current_loop.h" |
22 #include "media/gpu/accelerated_video_decoder.h" | 23 #include "media/gpu/accelerated_video_decoder.h" |
23 #include "media/gpu/h264_decoder.h" | 24 #include "media/gpu/h264_decoder.h" |
24 #include "media/gpu/vaapi_picture.h" | 25 #include "media/gpu/vaapi_picture.h" |
25 #include "media/gpu/vp8_decoder.h" | 26 #include "media/gpu/vp8_decoder.h" |
26 #include "media/gpu/vp9_decoder.h" | 27 #include "media/gpu/vp9_decoder.h" |
27 #include "media/video/picture.h" | 28 #include "media/video/picture.h" |
28 #include "third_party/libva/va/va_dec_vp8.h" | 29 #include "third_party/libva/va/va_dec_vp8.h" |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 VaapiVideoDecodeAccelerator* vaapi_dec_; | 260 VaapiVideoDecodeAccelerator* vaapi_dec_; |
260 | 261 |
261 DISALLOW_COPY_AND_ASSIGN(VaapiVP9Accelerator); | 262 DISALLOW_COPY_AND_ASSIGN(VaapiVP9Accelerator); |
262 }; | 263 }; |
263 | 264 |
264 VaapiVideoDecodeAccelerator::InputBuffer::InputBuffer() : id(0) {} | 265 VaapiVideoDecodeAccelerator::InputBuffer::InputBuffer() : id(0) {} |
265 | 266 |
266 VaapiVideoDecodeAccelerator::InputBuffer::~InputBuffer() {} | 267 VaapiVideoDecodeAccelerator::InputBuffer::~InputBuffer() {} |
267 | 268 |
268 void VaapiVideoDecodeAccelerator::NotifyError(Error error) { | 269 void VaapiVideoDecodeAccelerator::NotifyError(Error error) { |
269 if (message_loop_ != base::MessageLoop::current()) { | 270 if (!task_runner_->BelongsToCurrentThread()) { |
270 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 271 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
271 message_loop_->PostTask( | 272 task_runner_->PostTask(FROM_HERE, |
272 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::NotifyError, | 273 base::Bind(&VaapiVideoDecodeAccelerator::NotifyError, |
273 weak_this_, error)); | 274 weak_this_, error)); |
274 return; | 275 return; |
275 } | 276 } |
276 | 277 |
277 // Post Cleanup() as a task so we don't recursively acquire lock_. | 278 // Post Cleanup() as a task so we don't recursively acquire lock_. |
278 message_loop_->PostTask( | 279 task_runner_->PostTask( |
279 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::Cleanup, weak_this_)); | 280 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::Cleanup, weak_this_)); |
280 | 281 |
281 LOG(ERROR) << "Notifying of error " << error; | 282 LOG(ERROR) << "Notifying of error " << error; |
282 if (client_) { | 283 if (client_) { |
283 client_->NotifyError(error); | 284 client_->NotifyError(error); |
284 client_ptr_factory_.reset(); | 285 client_ptr_factory_.reset(); |
285 } | 286 } |
286 } | 287 } |
287 | 288 |
288 VaapiPicture* VaapiVideoDecodeAccelerator::PictureById( | 289 VaapiPicture* VaapiVideoDecodeAccelerator::PictureById( |
289 int32_t picture_buffer_id) { | 290 int32_t picture_buffer_id) { |
290 Pictures::iterator it = pictures_.find(picture_buffer_id); | 291 Pictures::iterator it = pictures_.find(picture_buffer_id); |
291 if (it == pictures_.end()) { | 292 if (it == pictures_.end()) { |
292 LOG(WARNING) << "Picture id " << picture_buffer_id << " does not exist"; | 293 LOG(WARNING) << "Picture id " << picture_buffer_id << " does not exist"; |
293 return NULL; | 294 return NULL; |
294 } | 295 } |
295 | 296 |
296 return it->second.get(); | 297 return it->second.get(); |
297 } | 298 } |
298 | 299 |
299 VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator( | 300 VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator( |
300 const MakeGLContextCurrentCallback& make_context_current_cb, | 301 const MakeGLContextCurrentCallback& make_context_current_cb, |
301 const BindGLImageCallback& bind_image_cb) | 302 const BindGLImageCallback& bind_image_cb) |
302 : state_(kUninitialized), | 303 : state_(kUninitialized), |
303 input_ready_(&lock_), | 304 input_ready_(&lock_), |
304 surfaces_available_(&lock_), | 305 surfaces_available_(&lock_), |
305 message_loop_(base::MessageLoop::current()), | 306 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
306 decoder_thread_("VaapiDecoderThread"), | 307 decoder_thread_("VaapiDecoderThread"), |
307 num_frames_at_client_(0), | 308 num_frames_at_client_(0), |
308 num_stream_bufs_at_decoder_(0), | 309 num_stream_bufs_at_decoder_(0), |
309 finish_flush_pending_(false), | 310 finish_flush_pending_(false), |
310 awaiting_va_surfaces_recycle_(false), | 311 awaiting_va_surfaces_recycle_(false), |
311 requested_num_pics_(0), | 312 requested_num_pics_(0), |
312 make_context_current_cb_(make_context_current_cb), | 313 make_context_current_cb_(make_context_current_cb), |
313 bind_image_cb_(bind_image_cb), | 314 bind_image_cb_(bind_image_cb), |
314 weak_this_factory_(this) { | 315 weak_this_factory_(this) { |
315 weak_this_ = weak_this_factory_.GetWeakPtr(); | 316 weak_this_ = weak_this_factory_.GetWeakPtr(); |
316 va_surface_release_cb_ = BindToCurrentLoop( | 317 va_surface_release_cb_ = BindToCurrentLoop( |
317 base::Bind(&VaapiVideoDecodeAccelerator::RecycleVASurfaceID, weak_this_)); | 318 base::Bind(&VaapiVideoDecodeAccelerator::RecycleVASurfaceID, weak_this_)); |
318 } | 319 } |
319 | 320 |
320 VaapiVideoDecodeAccelerator::~VaapiVideoDecodeAccelerator() { | 321 VaapiVideoDecodeAccelerator::~VaapiVideoDecodeAccelerator() { |
321 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 322 DCHECK(task_runner_->BelongsToCurrentThread()); |
322 } | 323 } |
323 | 324 |
324 bool VaapiVideoDecodeAccelerator::Initialize(const Config& config, | 325 bool VaapiVideoDecodeAccelerator::Initialize(const Config& config, |
325 Client* client) { | 326 Client* client) { |
326 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 327 DCHECK(task_runner_->BelongsToCurrentThread()); |
327 | 328 |
328 if (config.is_encrypted) { | 329 if (config.is_encrypted) { |
329 NOTREACHED() << "Encrypted streams are not supported for this VDA"; | 330 NOTREACHED() << "Encrypted streams are not supported for this VDA"; |
330 return false; | 331 return false; |
331 } | 332 } |
332 | 333 |
333 if (config.output_mode != Config::OutputMode::ALLOCATE && | 334 if (config.output_mode != Config::OutputMode::ALLOCATE && |
334 config.output_mode != Config::OutputMode::IMPORT) { | 335 config.output_mode != Config::OutputMode::IMPORT) { |
335 NOTREACHED() << "Only ALLOCATE and IMPORT OutputModes are supported"; | 336 NOTREACHED() << "Only ALLOCATE and IMPORT OutputModes are supported"; |
336 } | 337 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 | 387 |
387 state_ = kIdle; | 388 state_ = kIdle; |
388 output_mode_ = config.output_mode; | 389 output_mode_ = config.output_mode; |
389 return true; | 390 return true; |
390 } | 391 } |
391 | 392 |
392 void VaapiVideoDecodeAccelerator::OutputPicture( | 393 void VaapiVideoDecodeAccelerator::OutputPicture( |
393 const scoped_refptr<VASurface>& va_surface, | 394 const scoped_refptr<VASurface>& va_surface, |
394 int32_t input_id, | 395 int32_t input_id, |
395 VaapiPicture* picture) { | 396 VaapiPicture* picture) { |
396 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 397 DCHECK(task_runner_->BelongsToCurrentThread()); |
397 | 398 |
398 int32_t output_id = picture->picture_buffer_id(); | 399 int32_t output_id = picture->picture_buffer_id(); |
399 | 400 |
400 TRACE_EVENT2("Video Decoder", "VAVDA::OutputSurface", "input_id", input_id, | 401 TRACE_EVENT2("Video Decoder", "VAVDA::OutputSurface", "input_id", input_id, |
401 "output_id", output_id); | 402 "output_id", output_id); |
402 | 403 |
403 DVLOG(3) << "Outputting VASurface " << va_surface->id() | 404 DVLOG(3) << "Outputting VASurface " << va_surface->id() |
404 << " into pixmap bound to picture buffer id " << output_id; | 405 << " into pixmap bound to picture buffer id " << output_id; |
405 | 406 |
406 RETURN_AND_NOTIFY_ON_FAILURE(picture->DownloadFromSurface(va_surface), | 407 RETURN_AND_NOTIFY_ON_FAILURE(picture->DownloadFromSurface(va_surface), |
407 "Failed putting surface into pixmap", | 408 "Failed putting surface into pixmap", |
408 PLATFORM_FAILURE, ); | 409 PLATFORM_FAILURE, ); |
409 | 410 |
410 // Notify the client a picture is ready to be displayed. | 411 // Notify the client a picture is ready to be displayed. |
411 ++num_frames_at_client_; | 412 ++num_frames_at_client_; |
412 TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_); | 413 TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_); |
413 DVLOG(4) << "Notifying output picture id " << output_id | 414 DVLOG(4) << "Notifying output picture id " << output_id |
414 << " for input " << input_id << " is ready"; | 415 << " for input " << input_id << " is ready"; |
415 // TODO(posciak): Use visible size from decoder here instead | 416 // TODO(posciak): Use visible size from decoder here instead |
416 // (crbug.com/402760). Passing (0, 0) results in the client using the | 417 // (crbug.com/402760). Passing (0, 0) results in the client using the |
417 // visible size extracted from the container instead. | 418 // visible size extracted from the container instead. |
418 if (client_) | 419 if (client_) |
419 client_->PictureReady( | 420 client_->PictureReady( |
420 Picture(output_id, input_id, gfx::Rect(0, 0), picture->AllowOverlay())); | 421 Picture(output_id, input_id, gfx::Rect(0, 0), picture->AllowOverlay())); |
421 } | 422 } |
422 | 423 |
423 void VaapiVideoDecodeAccelerator::TryOutputSurface() { | 424 void VaapiVideoDecodeAccelerator::TryOutputSurface() { |
424 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 425 DCHECK(task_runner_->BelongsToCurrentThread()); |
425 | 426 |
426 // Handle Destroy() arriving while pictures are queued for output. | 427 // Handle Destroy() arriving while pictures are queued for output. |
427 if (!client_) | 428 if (!client_) |
428 return; | 429 return; |
429 | 430 |
430 if (pending_output_cbs_.empty() || output_buffers_.empty()) | 431 if (pending_output_cbs_.empty() || output_buffers_.empty()) |
431 return; | 432 return; |
432 | 433 |
433 OutputCB output_cb = pending_output_cbs_.front(); | 434 OutputCB output_cb = pending_output_cbs_.front(); |
434 pending_output_cbs_.pop(); | 435 pending_output_cbs_.pop(); |
435 | 436 |
436 VaapiPicture* picture = PictureById(output_buffers_.front()); | 437 VaapiPicture* picture = PictureById(output_buffers_.front()); |
437 DCHECK(picture); | 438 DCHECK(picture); |
438 output_buffers_.pop(); | 439 output_buffers_.pop(); |
439 | 440 |
440 output_cb.Run(picture); | 441 output_cb.Run(picture); |
441 | 442 |
442 if (finish_flush_pending_ && pending_output_cbs_.empty()) | 443 if (finish_flush_pending_ && pending_output_cbs_.empty()) |
443 FinishFlush(); | 444 FinishFlush(); |
444 } | 445 } |
445 | 446 |
446 void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer( | 447 void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer( |
447 const BitstreamBuffer& bitstream_buffer) { | 448 const BitstreamBuffer& bitstream_buffer) { |
448 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 449 DCHECK(task_runner_->BelongsToCurrentThread()); |
449 TRACE_EVENT1("Video Decoder", "MapAndQueueNewInputBuffer", "input_id", | 450 TRACE_EVENT1("Video Decoder", "MapAndQueueNewInputBuffer", "input_id", |
450 bitstream_buffer.id()); | 451 bitstream_buffer.id()); |
451 | 452 |
452 DVLOG(4) << "Mapping new input buffer id: " << bitstream_buffer.id() | 453 DVLOG(4) << "Mapping new input buffer id: " << bitstream_buffer.id() |
453 << " size: " << (int)bitstream_buffer.size(); | 454 << " size: " << (int)bitstream_buffer.size(); |
454 | 455 |
455 std::unique_ptr<SharedMemoryRegion> shm( | 456 std::unique_ptr<SharedMemoryRegion> shm( |
456 new SharedMemoryRegion(bitstream_buffer, true)); | 457 new SharedMemoryRegion(bitstream_buffer, true)); |
457 | 458 |
458 // Skip empty buffers. | 459 // Skip empty buffers. |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 } | 526 } |
526 | 527 |
527 void VaapiVideoDecodeAccelerator::ReturnCurrInputBuffer_Locked() { | 528 void VaapiVideoDecodeAccelerator::ReturnCurrInputBuffer_Locked() { |
528 lock_.AssertAcquired(); | 529 lock_.AssertAcquired(); |
529 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 530 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
530 DCHECK(curr_input_buffer_.get()); | 531 DCHECK(curr_input_buffer_.get()); |
531 | 532 |
532 int32_t id = curr_input_buffer_->id; | 533 int32_t id = curr_input_buffer_->id; |
533 curr_input_buffer_.reset(); | 534 curr_input_buffer_.reset(); |
534 DVLOG(4) << "End of input buffer " << id; | 535 DVLOG(4) << "End of input buffer " << id; |
535 message_loop_->PostTask( | 536 task_runner_->PostTask( |
536 FROM_HERE, base::Bind(&Client::NotifyEndOfBitstreamBuffer, client_, id)); | 537 FROM_HERE, base::Bind(&Client::NotifyEndOfBitstreamBuffer, client_, id)); |
537 | 538 |
538 --num_stream_bufs_at_decoder_; | 539 --num_stream_bufs_at_decoder_; |
539 TRACE_COUNTER1("Video Decoder", "Stream buffers at decoder", | 540 TRACE_COUNTER1("Video Decoder", "Stream buffers at decoder", |
540 num_stream_bufs_at_decoder_); | 541 num_stream_bufs_at_decoder_); |
541 } | 542 } |
542 | 543 |
543 // TODO(posciak): refactor the whole class to remove sleeping in wait for | 544 // TODO(posciak): refactor the whole class to remove sleeping in wait for |
544 // surfaces, and reschedule DecodeTask instead. | 545 // surfaces, and reschedule DecodeTask instead. |
545 bool VaapiVideoDecodeAccelerator::WaitForSurfaces_Locked() { | 546 bool VaapiVideoDecodeAccelerator::WaitForSurfaces_Locked() { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
580 // This is the main decode function of the decoder and while keeping | 581 // This is the main decode function of the decoder and while keeping |
581 // the lock for its duration would be fine, it would defeat the purpose | 582 // the lock for its duration would be fine, it would defeat the purpose |
582 // of having a separate decoder thread. | 583 // of having a separate decoder thread. |
583 base::AutoUnlock auto_unlock(lock_); | 584 base::AutoUnlock auto_unlock(lock_); |
584 res = decoder_->Decode(); | 585 res = decoder_->Decode(); |
585 } | 586 } |
586 | 587 |
587 switch (res) { | 588 switch (res) { |
588 case AcceleratedVideoDecoder::kAllocateNewSurfaces: | 589 case AcceleratedVideoDecoder::kAllocateNewSurfaces: |
589 DVLOG(1) << "Decoder requesting a new set of surfaces"; | 590 DVLOG(1) << "Decoder requesting a new set of surfaces"; |
590 message_loop_->PostTask( | 591 task_runner_->PostTask( |
591 FROM_HERE, | 592 FROM_HERE, |
592 base::Bind(&VaapiVideoDecodeAccelerator::InitiateSurfaceSetChange, | 593 base::Bind(&VaapiVideoDecodeAccelerator::InitiateSurfaceSetChange, |
593 weak_this_, decoder_->GetRequiredNumOfPictures(), | 594 weak_this_, decoder_->GetRequiredNumOfPictures(), |
594 decoder_->GetPicSize())); | 595 decoder_->GetPicSize())); |
595 // We'll get rescheduled once ProvidePictureBuffers() finishes. | 596 // We'll get rescheduled once ProvidePictureBuffers() finishes. |
596 return; | 597 return; |
597 | 598 |
598 case AcceleratedVideoDecoder::kRanOutOfStreamData: | 599 case AcceleratedVideoDecoder::kRanOutOfStreamData: |
599 ReturnCurrInputBuffer_Locked(); | 600 ReturnCurrInputBuffer_Locked(); |
600 break; | 601 break; |
601 | 602 |
602 case AcceleratedVideoDecoder::kRanOutOfSurfaces: | 603 case AcceleratedVideoDecoder::kRanOutOfSurfaces: |
603 // No more output buffers in the decoder, try getting more or go to | 604 // No more output buffers in the decoder, try getting more or go to |
604 // sleep waiting for them. | 605 // sleep waiting for them. |
605 if (!WaitForSurfaces_Locked()) | 606 if (!WaitForSurfaces_Locked()) |
606 return; | 607 return; |
607 | 608 |
608 break; | 609 break; |
609 | 610 |
610 case AcceleratedVideoDecoder::kDecodeError: | 611 case AcceleratedVideoDecoder::kDecodeError: |
611 RETURN_AND_NOTIFY_ON_FAILURE(false, "Error decoding stream", | 612 RETURN_AND_NOTIFY_ON_FAILURE(false, "Error decoding stream", |
612 PLATFORM_FAILURE, ); | 613 PLATFORM_FAILURE, ); |
613 return; | 614 return; |
614 } | 615 } |
615 } | 616 } |
616 } | 617 } |
617 | 618 |
618 void VaapiVideoDecodeAccelerator::InitiateSurfaceSetChange(size_t num_pics, | 619 void VaapiVideoDecodeAccelerator::InitiateSurfaceSetChange(size_t num_pics, |
619 gfx::Size size) { | 620 gfx::Size size) { |
620 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 621 DCHECK(task_runner_->BelongsToCurrentThread()); |
621 DCHECK(!awaiting_va_surfaces_recycle_); | 622 DCHECK(!awaiting_va_surfaces_recycle_); |
622 | 623 |
623 // At this point decoder has stopped running and has already posted onto our | 624 // At this point decoder has stopped running and has already posted onto our |
624 // loop any remaining output request callbacks, which executed before we got | 625 // loop any remaining output request callbacks, which executed before we got |
625 // here. Some of them might have been pended though, because we might not | 626 // here. Some of them might have been pended though, because we might not |
626 // have had enough TFPictures to output surfaces to. Initiate a wait cycle, | 627 // have had enough TFPictures to output surfaces to. Initiate a wait cycle, |
627 // which will wait for client to return enough PictureBuffers to us, so that | 628 // which will wait for client to return enough PictureBuffers to us, so that |
628 // we can finish all pending output callbacks, releasing associated surfaces. | 629 // we can finish all pending output callbacks, releasing associated surfaces. |
629 DVLOG(1) << "Initiating surface set change"; | 630 DVLOG(1) << "Initiating surface set change"; |
630 awaiting_va_surfaces_recycle_ = true; | 631 awaiting_va_surfaces_recycle_ = true; |
(...skipping 10 matching lines...) Expand all Loading... |
641 case gfx::BufferFormat::BGRA_8888: | 642 case gfx::BufferFormat::BGRA_8888: |
642 return PIXEL_FORMAT_ARGB; | 643 return PIXEL_FORMAT_ARGB; |
643 | 644 |
644 default: | 645 default: |
645 LOG(FATAL) << "Add more cases as needed"; | 646 LOG(FATAL) << "Add more cases as needed"; |
646 return PIXEL_FORMAT_UNKNOWN; | 647 return PIXEL_FORMAT_UNKNOWN; |
647 } | 648 } |
648 } | 649 } |
649 | 650 |
650 void VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange() { | 651 void VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange() { |
651 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 652 DCHECK(task_runner_->BelongsToCurrentThread()); |
652 | 653 |
653 if (!awaiting_va_surfaces_recycle_) | 654 if (!awaiting_va_surfaces_recycle_) |
654 return; | 655 return; |
655 | 656 |
656 if (!pending_output_cbs_.empty() || | 657 if (!pending_output_cbs_.empty() || |
657 pictures_.size() != available_va_surfaces_.size()) { | 658 pictures_.size() != available_va_surfaces_.size()) { |
658 // Either: | 659 // Either: |
659 // 1. Not all pending pending output callbacks have been executed yet. | 660 // 1. Not all pending pending output callbacks have been executed yet. |
660 // Wait for the client to return enough pictures and retry later. | 661 // Wait for the client to return enough pictures and retry later. |
661 // 2. The above happened and all surface release callbacks have been posted | 662 // 2. The above happened and all surface release callbacks have been posted |
662 // as the result, but not all have executed yet. Post ourselves after them | 663 // as the result, but not all have executed yet. Post ourselves after them |
663 // to let them release surfaces. | 664 // to let them release surfaces. |
664 DVLOG(2) << "Awaiting pending output/surface release callbacks to finish"; | 665 DVLOG(2) << "Awaiting pending output/surface release callbacks to finish"; |
665 message_loop_->PostTask( | 666 task_runner_->PostTask( |
666 FROM_HERE, | 667 FROM_HERE, |
667 base::Bind(&VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange, | 668 base::Bind(&VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange, |
668 weak_this_)); | 669 weak_this_)); |
669 return; | 670 return; |
670 } | 671 } |
671 | 672 |
672 // All surfaces released, destroy them and dismiss all PictureBuffers. | 673 // All surfaces released, destroy them and dismiss all PictureBuffers. |
673 awaiting_va_surfaces_recycle_ = false; | 674 awaiting_va_surfaces_recycle_ = false; |
674 available_va_surfaces_.clear(); | 675 available_va_surfaces_.clear(); |
675 vaapi_wrapper_->DestroySurfaces(); | 676 vaapi_wrapper_->DestroySurfaces(); |
676 | 677 |
677 for (Pictures::iterator iter = pictures_.begin(); iter != pictures_.end(); | 678 for (Pictures::iterator iter = pictures_.begin(); iter != pictures_.end(); |
678 ++iter) { | 679 ++iter) { |
679 DVLOG(2) << "Dismissing picture id: " << iter->first; | 680 DVLOG(2) << "Dismissing picture id: " << iter->first; |
680 if (client_) | 681 if (client_) |
681 client_->DismissPictureBuffer(iter->first); | 682 client_->DismissPictureBuffer(iter->first); |
682 } | 683 } |
683 pictures_.clear(); | 684 pictures_.clear(); |
684 | 685 |
685 // And ask for a new set as requested. | 686 // And ask for a new set as requested. |
686 DVLOG(1) << "Requesting " << requested_num_pics_ | 687 DVLOG(1) << "Requesting " << requested_num_pics_ |
687 << " pictures of size: " << requested_pic_size_.ToString(); | 688 << " pictures of size: " << requested_pic_size_.ToString(); |
688 | 689 |
689 VideoPixelFormat format = | 690 VideoPixelFormat format = |
690 BufferFormatToVideoPixelFormat(kOutputPictureFormat); | 691 BufferFormatToVideoPixelFormat(kOutputPictureFormat); |
691 message_loop_->PostTask( | 692 task_runner_->PostTask( |
692 FROM_HERE, base::Bind(&Client::ProvidePictureBuffers, client_, | 693 FROM_HERE, base::Bind(&Client::ProvidePictureBuffers, client_, |
693 requested_num_pics_, format, 1, requested_pic_size_, | 694 requested_num_pics_, format, 1, requested_pic_size_, |
694 VaapiPicture::GetGLTextureTarget())); | 695 VaapiPicture::GetGLTextureTarget())); |
695 } | 696 } |
696 | 697 |
697 void VaapiVideoDecodeAccelerator::Decode( | 698 void VaapiVideoDecodeAccelerator::Decode( |
698 const BitstreamBuffer& bitstream_buffer) { | 699 const BitstreamBuffer& bitstream_buffer) { |
699 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 700 DCHECK(task_runner_->BelongsToCurrentThread()); |
700 | 701 |
701 TRACE_EVENT1("Video Decoder", "VAVDA::Decode", "Buffer id", | 702 TRACE_EVENT1("Video Decoder", "VAVDA::Decode", "Buffer id", |
702 bitstream_buffer.id()); | 703 bitstream_buffer.id()); |
703 | 704 |
704 if (bitstream_buffer.id() < 0) { | 705 if (bitstream_buffer.id() < 0) { |
705 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) | 706 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) |
706 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); | 707 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); |
707 LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id(); | 708 LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id(); |
708 NotifyError(INVALID_ARGUMENT); | 709 NotifyError(INVALID_ARGUMENT); |
709 return; | 710 return; |
(...skipping 22 matching lines...) Expand all Loading... |
732 default: | 733 default: |
733 RETURN_AND_NOTIFY_ON_FAILURE( | 734 RETURN_AND_NOTIFY_ON_FAILURE( |
734 false, "Decode request from client in invalid state: " << state_, | 735 false, "Decode request from client in invalid state: " << state_, |
735 PLATFORM_FAILURE, ); | 736 PLATFORM_FAILURE, ); |
736 break; | 737 break; |
737 } | 738 } |
738 } | 739 } |
739 | 740 |
740 void VaapiVideoDecodeAccelerator::RecycleVASurfaceID( | 741 void VaapiVideoDecodeAccelerator::RecycleVASurfaceID( |
741 VASurfaceID va_surface_id) { | 742 VASurfaceID va_surface_id) { |
742 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 743 DCHECK(task_runner_->BelongsToCurrentThread()); |
743 base::AutoLock auto_lock(lock_); | 744 base::AutoLock auto_lock(lock_); |
744 | 745 |
745 available_va_surfaces_.push_back(va_surface_id); | 746 available_va_surfaces_.push_back(va_surface_id); |
746 surfaces_available_.Signal(); | 747 surfaces_available_.Signal(); |
747 } | 748 } |
748 | 749 |
749 void VaapiVideoDecodeAccelerator::AssignPictureBuffers( | 750 void VaapiVideoDecodeAccelerator::AssignPictureBuffers( |
750 const std::vector<PictureBuffer>& buffers) { | 751 const std::vector<PictureBuffer>& buffers) { |
751 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 752 DCHECK(task_runner_->BelongsToCurrentThread()); |
752 | 753 |
753 base::AutoLock auto_lock(lock_); | 754 base::AutoLock auto_lock(lock_); |
754 DCHECK(pictures_.empty()); | 755 DCHECK(pictures_.empty()); |
755 | 756 |
756 while (!output_buffers_.empty()) | 757 while (!output_buffers_.empty()) |
757 output_buffers_.pop(); | 758 output_buffers_.pop(); |
758 | 759 |
759 RETURN_AND_NOTIFY_ON_FAILURE( | 760 RETURN_AND_NOTIFY_ON_FAILURE( |
760 buffers.size() >= requested_num_pics_, | 761 buffers.size() >= requested_num_pics_, |
761 "Got an invalid number of picture buffers. (Got " << buffers.size() | 762 "Got an invalid number of picture buffers. (Got " << buffers.size() |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
809 for (const auto& fd : handle.native_pixmap_handle.fds) { | 810 for (const auto& fd : handle.native_pixmap_handle.fds) { |
810 // Close the fd by wrapping it in a ScopedFD and letting | 811 // Close the fd by wrapping it in a ScopedFD and letting |
811 // it fall out of scope. | 812 // it fall out of scope. |
812 base::ScopedFD scoped_fd(fd.fd); | 813 base::ScopedFD scoped_fd(fd.fd); |
813 } | 814 } |
814 } | 815 } |
815 | 816 |
816 void VaapiVideoDecodeAccelerator::ImportBufferForPicture( | 817 void VaapiVideoDecodeAccelerator::ImportBufferForPicture( |
817 int32_t picture_buffer_id, | 818 int32_t picture_buffer_id, |
818 const gfx::GpuMemoryBufferHandle& gpu_memory_buffer_handle) { | 819 const gfx::GpuMemoryBufferHandle& gpu_memory_buffer_handle) { |
819 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 820 DCHECK(task_runner_->BelongsToCurrentThread()); |
820 DVLOG(2) << "Importing picture id: " << picture_buffer_id; | 821 DVLOG(2) << "Importing picture id: " << picture_buffer_id; |
821 | 822 |
822 if (output_mode_ != Config::OutputMode::IMPORT) { | 823 if (output_mode_ != Config::OutputMode::IMPORT) { |
823 CloseGpuMemoryBufferHandle(gpu_memory_buffer_handle); | 824 CloseGpuMemoryBufferHandle(gpu_memory_buffer_handle); |
824 LOG(ERROR) << "Cannot import in non-import mode"; | 825 LOG(ERROR) << "Cannot import in non-import mode"; |
825 NotifyError(INVALID_ARGUMENT); | 826 NotifyError(INVALID_ARGUMENT); |
826 return; | 827 return; |
827 } | 828 } |
828 | 829 |
829 if (gpu_memory_buffer_handle.native_pixmap_handle.fds.size() != 1) { | 830 if (gpu_memory_buffer_handle.native_pixmap_handle.fds.size() != 1) { |
(...skipping 24 matching lines...) Expand all Loading... |
854 NotifyError(PLATFORM_FAILURE); | 855 NotifyError(PLATFORM_FAILURE); |
855 return; | 856 return; |
856 } | 857 } |
857 | 858 |
858 ReusePictureBuffer(picture_buffer_id); | 859 ReusePictureBuffer(picture_buffer_id); |
859 } | 860 } |
860 #endif | 861 #endif |
861 | 862 |
862 void VaapiVideoDecodeAccelerator::ReusePictureBuffer( | 863 void VaapiVideoDecodeAccelerator::ReusePictureBuffer( |
863 int32_t picture_buffer_id) { | 864 int32_t picture_buffer_id) { |
864 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 865 DCHECK(task_runner_->BelongsToCurrentThread()); |
865 TRACE_EVENT1("Video Decoder", "VAVDA::ReusePictureBuffer", "Picture id", | 866 TRACE_EVENT1("Video Decoder", "VAVDA::ReusePictureBuffer", "Picture id", |
866 picture_buffer_id); | 867 picture_buffer_id); |
867 | 868 |
868 if (!PictureById(picture_buffer_id)) { | 869 if (!PictureById(picture_buffer_id)) { |
869 // It's possible that we've already posted a DismissPictureBuffer for this | 870 // It's possible that we've already posted a DismissPictureBuffer for this |
870 // picture, but it has not yet executed when this ReusePictureBuffer | 871 // picture, but it has not yet executed when this ReusePictureBuffer |
871 // was posted to us by the client. In that case just ignore this (we've | 872 // was posted to us by the client. In that case just ignore this (we've |
872 // already dismissed it and accounted for that). | 873 // already dismissed it and accounted for that). |
873 DVLOG(3) << "got picture id=" << picture_buffer_id | 874 DVLOG(3) << "got picture id=" << picture_buffer_id |
874 << " not in use (anymore?)."; | 875 << " not in use (anymore?)."; |
(...skipping 13 matching lines...) Expand all Loading... |
888 | 889 |
889 // First flush all the pictures that haven't been outputted, notifying the | 890 // First flush all the pictures that haven't been outputted, notifying the |
890 // client to output them. | 891 // client to output them. |
891 bool res = decoder_->Flush(); | 892 bool res = decoder_->Flush(); |
892 RETURN_AND_NOTIFY_ON_FAILURE(res, "Failed flushing the decoder.", | 893 RETURN_AND_NOTIFY_ON_FAILURE(res, "Failed flushing the decoder.", |
893 PLATFORM_FAILURE, ); | 894 PLATFORM_FAILURE, ); |
894 | 895 |
895 // Put the decoder in idle state, ready to resume. | 896 // Put the decoder in idle state, ready to resume. |
896 decoder_->Reset(); | 897 decoder_->Reset(); |
897 | 898 |
898 message_loop_->PostTask( | 899 task_runner_->PostTask( |
899 FROM_HERE, | 900 FROM_HERE, |
900 base::Bind(&VaapiVideoDecodeAccelerator::FinishFlush, weak_this_)); | 901 base::Bind(&VaapiVideoDecodeAccelerator::FinishFlush, weak_this_)); |
901 } | 902 } |
902 | 903 |
903 void VaapiVideoDecodeAccelerator::Flush() { | 904 void VaapiVideoDecodeAccelerator::Flush() { |
904 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 905 DCHECK(task_runner_->BelongsToCurrentThread()); |
905 DVLOG(1) << "Got flush request"; | 906 DVLOG(1) << "Got flush request"; |
906 | 907 |
907 base::AutoLock auto_lock(lock_); | 908 base::AutoLock auto_lock(lock_); |
908 state_ = kFlushing; | 909 state_ = kFlushing; |
909 // Queue a flush task after all existing decoding tasks to clean up. | 910 // Queue a flush task after all existing decoding tasks to clean up. |
910 decoder_thread_task_runner_->PostTask( | 911 decoder_thread_task_runner_->PostTask( |
911 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::FlushTask, | 912 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::FlushTask, |
912 base::Unretained(this))); | 913 base::Unretained(this))); |
913 | 914 |
914 input_ready_.Signal(); | 915 input_ready_.Signal(); |
915 surfaces_available_.Signal(); | 916 surfaces_available_.Signal(); |
916 } | 917 } |
917 | 918 |
918 void VaapiVideoDecodeAccelerator::FinishFlush() { | 919 void VaapiVideoDecodeAccelerator::FinishFlush() { |
919 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 920 DCHECK(task_runner_->BelongsToCurrentThread()); |
920 | 921 |
921 finish_flush_pending_ = false; | 922 finish_flush_pending_ = false; |
922 | 923 |
923 base::AutoLock auto_lock(lock_); | 924 base::AutoLock auto_lock(lock_); |
924 if (state_ != kFlushing) { | 925 if (state_ != kFlushing) { |
925 DCHECK_EQ(state_, kDestroying); | 926 DCHECK_EQ(state_, kDestroying); |
926 return; // We could've gotten destroyed already. | 927 return; // We could've gotten destroyed already. |
927 } | 928 } |
928 | 929 |
929 // Still waiting for textures from client to finish outputting all pending | 930 // Still waiting for textures from client to finish outputting all pending |
930 // frames. Try again later. | 931 // frames. Try again later. |
931 if (!pending_output_cbs_.empty()) { | 932 if (!pending_output_cbs_.empty()) { |
932 finish_flush_pending_ = true; | 933 finish_flush_pending_ = true; |
933 return; | 934 return; |
934 } | 935 } |
935 | 936 |
936 state_ = kIdle; | 937 state_ = kIdle; |
937 | 938 |
938 message_loop_->PostTask(FROM_HERE, | 939 task_runner_->PostTask(FROM_HERE, |
939 base::Bind(&Client::NotifyFlushDone, client_)); | 940 base::Bind(&Client::NotifyFlushDone, client_)); |
940 | 941 |
941 DVLOG(1) << "Flush finished"; | 942 DVLOG(1) << "Flush finished"; |
942 } | 943 } |
943 | 944 |
944 void VaapiVideoDecodeAccelerator::ResetTask() { | 945 void VaapiVideoDecodeAccelerator::ResetTask() { |
945 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 946 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
946 DVLOG(1) << "ResetTask"; | 947 DVLOG(1) << "ResetTask"; |
947 | 948 |
948 // All the decoding tasks from before the reset request from client are done | 949 // All the decoding tasks from before the reset request from client are done |
949 // by now, as this task was scheduled after them and client is expected not | 950 // by now, as this task was scheduled after them and client is expected not |
950 // to call Decode() after Reset() and before NotifyResetDone. | 951 // to call Decode() after Reset() and before NotifyResetDone. |
951 decoder_->Reset(); | 952 decoder_->Reset(); |
952 | 953 |
953 base::AutoLock auto_lock(lock_); | 954 base::AutoLock auto_lock(lock_); |
954 | 955 |
955 // Return current input buffer, if present. | 956 // Return current input buffer, if present. |
956 if (curr_input_buffer_.get()) | 957 if (curr_input_buffer_.get()) |
957 ReturnCurrInputBuffer_Locked(); | 958 ReturnCurrInputBuffer_Locked(); |
958 | 959 |
959 // And let client know that we are done with reset. | 960 // And let client know that we are done with reset. |
960 message_loop_->PostTask( | 961 task_runner_->PostTask( |
961 FROM_HERE, | 962 FROM_HERE, |
962 base::Bind(&VaapiVideoDecodeAccelerator::FinishReset, weak_this_)); | 963 base::Bind(&VaapiVideoDecodeAccelerator::FinishReset, weak_this_)); |
963 } | 964 } |
964 | 965 |
965 void VaapiVideoDecodeAccelerator::Reset() { | 966 void VaapiVideoDecodeAccelerator::Reset() { |
966 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 967 DCHECK(task_runner_->BelongsToCurrentThread()); |
967 DVLOG(1) << "Got reset request"; | 968 DVLOG(1) << "Got reset request"; |
968 | 969 |
969 // This will make any new decode tasks exit early. | 970 // This will make any new decode tasks exit early. |
970 base::AutoLock auto_lock(lock_); | 971 base::AutoLock auto_lock(lock_); |
971 state_ = kResetting; | 972 state_ = kResetting; |
972 finish_flush_pending_ = false; | 973 finish_flush_pending_ = false; |
973 | 974 |
974 // Drop all remaining input buffers, if present. | 975 // Drop all remaining input buffers, if present. |
975 while (!input_buffers_.empty()) { | 976 while (!input_buffers_.empty()) { |
976 message_loop_->PostTask( | 977 task_runner_->PostTask( |
977 FROM_HERE, base::Bind(&Client::NotifyEndOfBitstreamBuffer, client_, | 978 FROM_HERE, base::Bind(&Client::NotifyEndOfBitstreamBuffer, client_, |
978 input_buffers_.front()->id)); | 979 input_buffers_.front()->id)); |
979 input_buffers_.pop(); | 980 input_buffers_.pop(); |
980 } | 981 } |
981 | 982 |
982 decoder_thread_task_runner_->PostTask( | 983 decoder_thread_task_runner_->PostTask( |
983 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::ResetTask, | 984 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::ResetTask, |
984 base::Unretained(this))); | 985 base::Unretained(this))); |
985 | 986 |
986 input_ready_.Signal(); | 987 input_ready_.Signal(); |
987 surfaces_available_.Signal(); | 988 surfaces_available_.Signal(); |
988 } | 989 } |
989 | 990 |
990 void VaapiVideoDecodeAccelerator::FinishReset() { | 991 void VaapiVideoDecodeAccelerator::FinishReset() { |
991 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 992 DCHECK(task_runner_->BelongsToCurrentThread()); |
992 DVLOG(1) << "FinishReset"; | 993 DVLOG(1) << "FinishReset"; |
993 base::AutoLock auto_lock(lock_); | 994 base::AutoLock auto_lock(lock_); |
994 | 995 |
995 if (state_ != kResetting) { | 996 if (state_ != kResetting) { |
996 DCHECK(state_ == kDestroying || state_ == kUninitialized) << state_; | 997 DCHECK(state_ == kDestroying || state_ == kUninitialized) << state_; |
997 return; // We could've gotten destroyed already. | 998 return; // We could've gotten destroyed already. |
998 } | 999 } |
999 | 1000 |
1000 // Drop pending outputs. | 1001 // Drop pending outputs. |
1001 while (!pending_output_cbs_.empty()) | 1002 while (!pending_output_cbs_.empty()) |
1002 pending_output_cbs_.pop(); | 1003 pending_output_cbs_.pop(); |
1003 | 1004 |
1004 if (awaiting_va_surfaces_recycle_) { | 1005 if (awaiting_va_surfaces_recycle_) { |
1005 // Decoder requested a new surface set while we were waiting for it to | 1006 // Decoder requested a new surface set while we were waiting for it to |
1006 // finish the last DecodeTask, running at the time of Reset(). | 1007 // finish the last DecodeTask, running at the time of Reset(). |
1007 // Let the surface set change finish first before resetting. | 1008 // Let the surface set change finish first before resetting. |
1008 message_loop_->PostTask( | 1009 task_runner_->PostTask( |
1009 FROM_HERE, | 1010 FROM_HERE, |
1010 base::Bind(&VaapiVideoDecodeAccelerator::FinishReset, weak_this_)); | 1011 base::Bind(&VaapiVideoDecodeAccelerator::FinishReset, weak_this_)); |
1011 return; | 1012 return; |
1012 } | 1013 } |
1013 | 1014 |
1014 num_stream_bufs_at_decoder_ = 0; | 1015 num_stream_bufs_at_decoder_ = 0; |
1015 state_ = kIdle; | 1016 state_ = kIdle; |
1016 | 1017 |
1017 message_loop_->PostTask(FROM_HERE, | 1018 task_runner_->PostTask(FROM_HERE, |
1018 base::Bind(&Client::NotifyResetDone, client_)); | 1019 base::Bind(&Client::NotifyResetDone, client_)); |
1019 | 1020 |
1020 // The client might have given us new buffers via Decode() while we were | 1021 // The client might have given us new buffers via Decode() while we were |
1021 // resetting and might be waiting for our move, and not call Decode() anymore | 1022 // resetting and might be waiting for our move, and not call Decode() anymore |
1022 // until we return something. Post a DecodeTask() so that we won't | 1023 // until we return something. Post a DecodeTask() so that we won't |
1023 // sleep forever waiting for Decode() in that case. Having two of them | 1024 // sleep forever waiting for Decode() in that case. Having two of them |
1024 // in the pipe is harmless, the additional one will return as soon as it sees | 1025 // in the pipe is harmless, the additional one will return as soon as it sees |
1025 // that we are back in kDecoding state. | 1026 // that we are back in kDecoding state. |
1026 if (!input_buffers_.empty()) { | 1027 if (!input_buffers_.empty()) { |
1027 state_ = kDecoding; | 1028 state_ = kDecoding; |
1028 decoder_thread_task_runner_->PostTask( | 1029 decoder_thread_task_runner_->PostTask( |
1029 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask, | 1030 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask, |
1030 base::Unretained(this))); | 1031 base::Unretained(this))); |
1031 } | 1032 } |
1032 | 1033 |
1033 DVLOG(1) << "Reset finished"; | 1034 DVLOG(1) << "Reset finished"; |
1034 } | 1035 } |
1035 | 1036 |
1036 void VaapiVideoDecodeAccelerator::Cleanup() { | 1037 void VaapiVideoDecodeAccelerator::Cleanup() { |
1037 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 1038 DCHECK(task_runner_->BelongsToCurrentThread()); |
1038 | 1039 |
1039 base::AutoLock auto_lock(lock_); | 1040 base::AutoLock auto_lock(lock_); |
1040 if (state_ == kUninitialized || state_ == kDestroying) | 1041 if (state_ == kUninitialized || state_ == kDestroying) |
1041 return; | 1042 return; |
1042 | 1043 |
1043 DVLOG(1) << "Destroying VAVDA"; | 1044 DVLOG(1) << "Destroying VAVDA"; |
1044 state_ = kDestroying; | 1045 state_ = kDestroying; |
1045 | 1046 |
1046 client_ptr_factory_.reset(); | 1047 client_ptr_factory_.reset(); |
1047 weak_this_factory_.InvalidateWeakPtrs(); | 1048 weak_this_factory_.InvalidateWeakPtrs(); |
1048 | 1049 |
1049 // Signal all potential waiters on the decoder_thread_, let them early-exit, | 1050 // Signal all potential waiters on the decoder_thread_, let them early-exit, |
1050 // as we've just moved to the kDestroying state, and wait for all tasks | 1051 // as we've just moved to the kDestroying state, and wait for all tasks |
1051 // to finish. | 1052 // to finish. |
1052 input_ready_.Signal(); | 1053 input_ready_.Signal(); |
1053 surfaces_available_.Signal(); | 1054 surfaces_available_.Signal(); |
1054 { | 1055 { |
1055 base::AutoUnlock auto_unlock(lock_); | 1056 base::AutoUnlock auto_unlock(lock_); |
1056 decoder_thread_.Stop(); | 1057 decoder_thread_.Stop(); |
1057 } | 1058 } |
1058 | 1059 |
1059 state_ = kUninitialized; | 1060 state_ = kUninitialized; |
1060 } | 1061 } |
1061 | 1062 |
1062 void VaapiVideoDecodeAccelerator::Destroy() { | 1063 void VaapiVideoDecodeAccelerator::Destroy() { |
1063 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 1064 DCHECK(task_runner_->BelongsToCurrentThread()); |
1064 Cleanup(); | 1065 Cleanup(); |
1065 delete this; | 1066 delete this; |
1066 } | 1067 } |
1067 | 1068 |
1068 bool VaapiVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread( | 1069 bool VaapiVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread( |
1069 const base::WeakPtr<Client>& decode_client, | 1070 const base::WeakPtr<Client>& decode_client, |
1070 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { | 1071 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { |
1071 return false; | 1072 return false; |
1072 } | 1073 } |
1073 | 1074 |
1074 bool VaapiVideoDecodeAccelerator::DecodeSurface( | 1075 bool VaapiVideoDecodeAccelerator::DecodeSurface( |
1075 const scoped_refptr<VaapiDecodeSurface>& dec_surface) { | 1076 const scoped_refptr<VaapiDecodeSurface>& dec_surface) { |
1076 if (!vaapi_wrapper_->ExecuteAndDestroyPendingBuffers( | 1077 if (!vaapi_wrapper_->ExecuteAndDestroyPendingBuffers( |
1077 dec_surface->va_surface()->id())) { | 1078 dec_surface->va_surface()->id())) { |
1078 DVLOG(1) << "Failed decoding picture"; | 1079 DVLOG(1) << "Failed decoding picture"; |
1079 return false; | 1080 return false; |
1080 } | 1081 } |
1081 | 1082 |
1082 return true; | 1083 return true; |
1083 } | 1084 } |
1084 | 1085 |
1085 void VaapiVideoDecodeAccelerator::SurfaceReady( | 1086 void VaapiVideoDecodeAccelerator::SurfaceReady( |
1086 const scoped_refptr<VaapiDecodeSurface>& dec_surface) { | 1087 const scoped_refptr<VaapiDecodeSurface>& dec_surface) { |
1087 if (message_loop_ != base::MessageLoop::current()) { | 1088 if (!task_runner_->BelongsToCurrentThread()) { |
1088 message_loop_->PostTask( | 1089 task_runner_->PostTask( |
1089 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::SurfaceReady, | 1090 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::SurfaceReady, |
1090 weak_this_, dec_surface)); | 1091 weak_this_, dec_surface)); |
1091 return; | 1092 return; |
1092 } | 1093 } |
1093 | 1094 |
1094 DCHECK(!awaiting_va_surfaces_recycle_); | 1095 DCHECK(!awaiting_va_surfaces_recycle_); |
1095 | 1096 |
1096 { | 1097 { |
1097 base::AutoLock auto_lock(lock_); | 1098 base::AutoLock auto_lock(lock_); |
1098 // Drop any requests to output if we are resetting or being destroyed. | 1099 // Drop any requests to output if we are resetting or being destroyed. |
(...skipping 741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1840 return vaapi_pic->dec_surface(); | 1841 return vaapi_pic->dec_surface(); |
1841 } | 1842 } |
1842 | 1843 |
1843 // static | 1844 // static |
1844 VideoDecodeAccelerator::SupportedProfiles | 1845 VideoDecodeAccelerator::SupportedProfiles |
1845 VaapiVideoDecodeAccelerator::GetSupportedProfiles() { | 1846 VaapiVideoDecodeAccelerator::GetSupportedProfiles() { |
1846 return VaapiWrapper::GetSupportedDecodeProfiles(); | 1847 return VaapiWrapper::GetSupportedDecodeProfiles(); |
1847 } | 1848 } |
1848 | 1849 |
1849 } // namespace media | 1850 } // namespace media |
OLD | NEW |