| 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(ERROR) << "Picture id " << picture_buffer_id << " does not exist"; | 293 LOG(ERROR) << "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 19 matching lines...) Expand all Loading... |
| 849 NotifyError(PLATFORM_FAILURE); | 850 NotifyError(PLATFORM_FAILURE); |
| 850 return; | 851 return; |
| 851 } | 852 } |
| 852 | 853 |
| 853 ReusePictureBuffer(picture_buffer_id); | 854 ReusePictureBuffer(picture_buffer_id); |
| 854 } | 855 } |
| 855 #endif | 856 #endif |
| 856 | 857 |
| 857 void VaapiVideoDecodeAccelerator::ReusePictureBuffer( | 858 void VaapiVideoDecodeAccelerator::ReusePictureBuffer( |
| 858 int32_t picture_buffer_id) { | 859 int32_t picture_buffer_id) { |
| 859 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 860 DCHECK(task_runner_->BelongsToCurrentThread()) |
| 860 TRACE_EVENT1("Video Decoder", "VAVDA::ReusePictureBuffer", "Picture id", | 861 TRACE_EVENT1("Video Decoder", "VAVDA::ReusePictureBuffer", "Picture id", |
| 861 picture_buffer_id); | 862 picture_buffer_id); |
| 862 | 863 |
| 863 --num_frames_at_client_; | 864 --num_frames_at_client_; |
| 864 TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_); | 865 TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_); |
| 865 | 866 |
| 866 output_buffers_.push(picture_buffer_id); | 867 output_buffers_.push(picture_buffer_id); |
| 867 TryOutputSurface(); | 868 TryOutputSurface(); |
| 868 } | 869 } |
| 869 | 870 |
| 870 void VaapiVideoDecodeAccelerator::FlushTask() { | 871 void VaapiVideoDecodeAccelerator::FlushTask() { |
| 871 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 872 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 872 DVLOG(1) << "Flush task"; | 873 DVLOG(1) << "Flush task"; |
| 873 | 874 |
| 874 // First flush all the pictures that haven't been outputted, notifying the | 875 // First flush all the pictures that haven't been outputted, notifying the |
| 875 // client to output them. | 876 // client to output them. |
| 876 bool res = decoder_->Flush(); | 877 bool res = decoder_->Flush(); |
| 877 RETURN_AND_NOTIFY_ON_FAILURE(res, "Failed flushing the decoder.", | 878 RETURN_AND_NOTIFY_ON_FAILURE(res, "Failed flushing the decoder.", |
| 878 PLATFORM_FAILURE, ); | 879 PLATFORM_FAILURE, ); |
| 879 | 880 |
| 880 // Put the decoder in idle state, ready to resume. | 881 // Put the decoder in idle state, ready to resume. |
| 881 decoder_->Reset(); | 882 decoder_->Reset(); |
| 882 | 883 |
| 883 message_loop_->PostTask( | 884 task_runner_->PostTask( |
| 884 FROM_HERE, | 885 FROM_HERE, |
| 885 base::Bind(&VaapiVideoDecodeAccelerator::FinishFlush, weak_this_)); | 886 base::Bind(&VaapiVideoDecodeAccelerator::FinishFlush, weak_this_)); |
| 886 } | 887 } |
| 887 | 888 |
| 888 void VaapiVideoDecodeAccelerator::Flush() { | 889 void VaapiVideoDecodeAccelerator::Flush() { |
| 889 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 890 DCHECK(task_runner_->BelongsToCurrentThread()) |
| 890 DVLOG(1) << "Got flush request"; | 891 DVLOG(1) << "Got flush request"; |
| 891 | 892 |
| 892 base::AutoLock auto_lock(lock_); | 893 base::AutoLock auto_lock(lock_); |
| 893 state_ = kFlushing; | 894 state_ = kFlushing; |
| 894 // Queue a flush task after all existing decoding tasks to clean up. | 895 // Queue a flush task after all existing decoding tasks to clean up. |
| 895 decoder_thread_task_runner_->PostTask( | 896 decoder_thread_task_runner_->PostTask( |
| 896 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::FlushTask, | 897 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::FlushTask, |
| 897 base::Unretained(this))); | 898 base::Unretained(this))); |
| 898 | 899 |
| 899 input_ready_.Signal(); | 900 input_ready_.Signal(); |
| 900 surfaces_available_.Signal(); | 901 surfaces_available_.Signal(); |
| 901 } | 902 } |
| 902 | 903 |
| 903 void VaapiVideoDecodeAccelerator::FinishFlush() { | 904 void VaapiVideoDecodeAccelerator::FinishFlush() { |
| 904 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 905 DCHECK(task_runner_->BelongsToCurrentThread()) |
| 905 | 906 |
| 906 finish_flush_pending_ = false; | 907 finish_flush_pending_ = false; |
| 907 | 908 |
| 908 base::AutoLock auto_lock(lock_); | 909 base::AutoLock auto_lock(lock_); |
| 909 if (state_ != kFlushing) { | 910 if (state_ != kFlushing) { |
| 910 DCHECK_EQ(state_, kDestroying); | 911 DCHECK_EQ(state_, kDestroying); |
| 911 return; // We could've gotten destroyed already. | 912 return; // We could've gotten destroyed already. |
| 912 } | 913 } |
| 913 | 914 |
| 914 // Still waiting for textures from client to finish outputting all pending | 915 // Still waiting for textures from client to finish outputting all pending |
| 915 // frames. Try again later. | 916 // frames. Try again later. |
| 916 if (!pending_output_cbs_.empty()) { | 917 if (!pending_output_cbs_.empty()) { |
| 917 finish_flush_pending_ = true; | 918 finish_flush_pending_ = true; |
| 918 return; | 919 return; |
| 919 } | 920 } |
| 920 | 921 |
| 921 state_ = kIdle; | 922 state_ = kIdle; |
| 922 | 923 |
| 923 message_loop_->PostTask(FROM_HERE, | 924 task_runner_->PostTask(FROM_HERE, |
| 924 base::Bind(&Client::NotifyFlushDone, client_)); | 925 base::Bind(&Client::NotifyFlushDone, client_)); |
| 925 | 926 |
| 926 DVLOG(1) << "Flush finished"; | 927 DVLOG(1) << "Flush finished"; |
| 927 } | 928 } |
| 928 | 929 |
| 929 void VaapiVideoDecodeAccelerator::ResetTask() { | 930 void VaapiVideoDecodeAccelerator::ResetTask() { |
| 930 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 931 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 931 DVLOG(1) << "ResetTask"; | 932 DVLOG(1) << "ResetTask"; |
| 932 | 933 |
| 933 // All the decoding tasks from before the reset request from client are done | 934 // All the decoding tasks from before the reset request from client are done |
| 934 // by now, as this task was scheduled after them and client is expected not | 935 // by now, as this task was scheduled after them and client is expected not |
| 935 // to call Decode() after Reset() and before NotifyResetDone. | 936 // to call Decode() after Reset() and before NotifyResetDone. |
| 936 decoder_->Reset(); | 937 decoder_->Reset(); |
| 937 | 938 |
| 938 base::AutoLock auto_lock(lock_); | 939 base::AutoLock auto_lock(lock_); |
| 939 | 940 |
| 940 // Return current input buffer, if present. | 941 // Return current input buffer, if present. |
| 941 if (curr_input_buffer_.get()) | 942 if (curr_input_buffer_.get()) |
| 942 ReturnCurrInputBuffer_Locked(); | 943 ReturnCurrInputBuffer_Locked(); |
| 943 | 944 |
| 944 // And let client know that we are done with reset. | 945 // And let client know that we are done with reset. |
| 945 message_loop_->PostTask( | 946 task_runner_->PostTask( |
| 946 FROM_HERE, | 947 FROM_HERE, |
| 947 base::Bind(&VaapiVideoDecodeAccelerator::FinishReset, weak_this_)); | 948 base::Bind(&VaapiVideoDecodeAccelerator::FinishReset, weak_this_)); |
| 948 } | 949 } |
| 949 | 950 |
| 950 void VaapiVideoDecodeAccelerator::Reset() { | 951 void VaapiVideoDecodeAccelerator::Reset() { |
| 951 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 952 DCHECK(task_runner_->BelongsToCurrentThread()) |
| 952 DVLOG(1) << "Got reset request"; | 953 DVLOG(1) << "Got reset request"; |
| 953 | 954 |
| 954 // This will make any new decode tasks exit early. | 955 // This will make any new decode tasks exit early. |
| 955 base::AutoLock auto_lock(lock_); | 956 base::AutoLock auto_lock(lock_); |
| 956 state_ = kResetting; | 957 state_ = kResetting; |
| 957 finish_flush_pending_ = false; | 958 finish_flush_pending_ = false; |
| 958 | 959 |
| 959 // Drop all remaining input buffers, if present. | 960 // Drop all remaining input buffers, if present. |
| 960 while (!input_buffers_.empty()) { | 961 while (!input_buffers_.empty()) { |
| 961 message_loop_->PostTask( | 962 task_runner_->PostTask( |
| 962 FROM_HERE, base::Bind(&Client::NotifyEndOfBitstreamBuffer, client_, | 963 FROM_HERE, base::Bind(&Client::NotifyEndOfBitstreamBuffer, client_, |
| 963 input_buffers_.front()->id)); | 964 input_buffers_.front()->id)); |
| 964 input_buffers_.pop(); | 965 input_buffers_.pop(); |
| 965 } | 966 } |
| 966 | 967 |
| 967 decoder_thread_task_runner_->PostTask( | 968 decoder_thread_task_runner_->PostTask( |
| 968 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::ResetTask, | 969 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::ResetTask, |
| 969 base::Unretained(this))); | 970 base::Unretained(this))); |
| 970 | 971 |
| 971 input_ready_.Signal(); | 972 input_ready_.Signal(); |
| 972 surfaces_available_.Signal(); | 973 surfaces_available_.Signal(); |
| 973 } | 974 } |
| 974 | 975 |
| 975 void VaapiVideoDecodeAccelerator::FinishReset() { | 976 void VaapiVideoDecodeAccelerator::FinishReset() { |
| 976 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 977 DCHECK(task_runner_->BelongsToCurrentThread()) |
| 977 DVLOG(1) << "FinishReset"; | 978 DVLOG(1) << "FinishReset"; |
| 978 base::AutoLock auto_lock(lock_); | 979 base::AutoLock auto_lock(lock_); |
| 979 | 980 |
| 980 if (state_ != kResetting) { | 981 if (state_ != kResetting) { |
| 981 DCHECK(state_ == kDestroying || state_ == kUninitialized) << state_; | 982 DCHECK(state_ == kDestroying || state_ == kUninitialized) << state_; |
| 982 return; // We could've gotten destroyed already. | 983 return; // We could've gotten destroyed already. |
| 983 } | 984 } |
| 984 | 985 |
| 985 // Drop pending outputs. | 986 // Drop pending outputs. |
| 986 while (!pending_output_cbs_.empty()) | 987 while (!pending_output_cbs_.empty()) |
| 987 pending_output_cbs_.pop(); | 988 pending_output_cbs_.pop(); |
| 988 | 989 |
| 989 if (awaiting_va_surfaces_recycle_) { | 990 if (awaiting_va_surfaces_recycle_) { |
| 990 // Decoder requested a new surface set while we were waiting for it to | 991 // Decoder requested a new surface set while we were waiting for it to |
| 991 // finish the last DecodeTask, running at the time of Reset(). | 992 // finish the last DecodeTask, running at the time of Reset(). |
| 992 // Let the surface set change finish first before resetting. | 993 // Let the surface set change finish first before resetting. |
| 993 message_loop_->PostTask( | 994 task_runner_->PostTask( |
| 994 FROM_HERE, | 995 FROM_HERE, |
| 995 base::Bind(&VaapiVideoDecodeAccelerator::FinishReset, weak_this_)); | 996 base::Bind(&VaapiVideoDecodeAccelerator::FinishReset, weak_this_)); |
| 996 return; | 997 return; |
| 997 } | 998 } |
| 998 | 999 |
| 999 num_stream_bufs_at_decoder_ = 0; | 1000 num_stream_bufs_at_decoder_ = 0; |
| 1000 state_ = kIdle; | 1001 state_ = kIdle; |
| 1001 | 1002 |
| 1002 message_loop_->PostTask(FROM_HERE, | 1003 task_runner_->PostTask(FROM_HERE, |
| 1003 base::Bind(&Client::NotifyResetDone, client_)); | 1004 base::Bind(&Client::NotifyResetDone, client_)); |
| 1004 | 1005 |
| 1005 // The client might have given us new buffers via Decode() while we were | 1006 // The client might have given us new buffers via Decode() while we were |
| 1006 // resetting and might be waiting for our move, and not call Decode() anymore | 1007 // resetting and might be waiting for our move, and not call Decode() anymore |
| 1007 // until we return something. Post a DecodeTask() so that we won't | 1008 // until we return something. Post a DecodeTask() so that we won't |
| 1008 // sleep forever waiting for Decode() in that case. Having two of them | 1009 // sleep forever waiting for Decode() in that case. Having two of them |
| 1009 // in the pipe is harmless, the additional one will return as soon as it sees | 1010 // in the pipe is harmless, the additional one will return as soon as it sees |
| 1010 // that we are back in kDecoding state. | 1011 // that we are back in kDecoding state. |
| 1011 if (!input_buffers_.empty()) { | 1012 if (!input_buffers_.empty()) { |
| 1012 state_ = kDecoding; | 1013 state_ = kDecoding; |
| 1013 decoder_thread_task_runner_->PostTask( | 1014 decoder_thread_task_runner_->PostTask( |
| 1014 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask, | 1015 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask, |
| 1015 base::Unretained(this))); | 1016 base::Unretained(this))); |
| 1016 } | 1017 } |
| 1017 | 1018 |
| 1018 DVLOG(1) << "Reset finished"; | 1019 DVLOG(1) << "Reset finished"; |
| 1019 } | 1020 } |
| 1020 | 1021 |
| 1021 void VaapiVideoDecodeAccelerator::Cleanup() { | 1022 void VaapiVideoDecodeAccelerator::Cleanup() { |
| 1022 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 1023 DCHECK(task_runner_->BelongsToCurrentThread()) |
| 1023 | 1024 |
| 1024 base::AutoLock auto_lock(lock_); | 1025 base::AutoLock auto_lock(lock_); |
| 1025 if (state_ == kUninitialized || state_ == kDestroying) | 1026 if (state_ == kUninitialized || state_ == kDestroying) |
| 1026 return; | 1027 return; |
| 1027 | 1028 |
| 1028 DVLOG(1) << "Destroying VAVDA"; | 1029 DVLOG(1) << "Destroying VAVDA"; |
| 1029 state_ = kDestroying; | 1030 state_ = kDestroying; |
| 1030 | 1031 |
| 1031 client_ptr_factory_.reset(); | 1032 client_ptr_factory_.reset(); |
| 1032 weak_this_factory_.InvalidateWeakPtrs(); | 1033 weak_this_factory_.InvalidateWeakPtrs(); |
| 1033 | 1034 |
| 1034 // Signal all potential waiters on the decoder_thread_, let them early-exit, | 1035 // Signal all potential waiters on the decoder_thread_, let them early-exit, |
| 1035 // as we've just moved to the kDestroying state, and wait for all tasks | 1036 // as we've just moved to the kDestroying state, and wait for all tasks |
| 1036 // to finish. | 1037 // to finish. |
| 1037 input_ready_.Signal(); | 1038 input_ready_.Signal(); |
| 1038 surfaces_available_.Signal(); | 1039 surfaces_available_.Signal(); |
| 1039 { | 1040 { |
| 1040 base::AutoUnlock auto_unlock(lock_); | 1041 base::AutoUnlock auto_unlock(lock_); |
| 1041 decoder_thread_.Stop(); | 1042 decoder_thread_.Stop(); |
| 1042 } | 1043 } |
| 1043 | 1044 |
| 1044 state_ = kUninitialized; | 1045 state_ = kUninitialized; |
| 1045 } | 1046 } |
| 1046 | 1047 |
| 1047 void VaapiVideoDecodeAccelerator::Destroy() { | 1048 void VaapiVideoDecodeAccelerator::Destroy() { |
| 1048 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 1049 DCHECK(task_runner_->BelongsToCurrentThread()) |
| 1049 Cleanup(); | 1050 Cleanup(); |
| 1050 delete this; | 1051 delete this; |
| 1051 } | 1052 } |
| 1052 | 1053 |
| 1053 bool VaapiVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread( | 1054 bool VaapiVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread( |
| 1054 const base::WeakPtr<Client>& decode_client, | 1055 const base::WeakPtr<Client>& decode_client, |
| 1055 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { | 1056 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { |
| 1056 return false; | 1057 return false; |
| 1057 } | 1058 } |
| 1058 | 1059 |
| 1059 bool VaapiVideoDecodeAccelerator::DecodeSurface( | 1060 bool VaapiVideoDecodeAccelerator::DecodeSurface( |
| 1060 const scoped_refptr<VaapiDecodeSurface>& dec_surface) { | 1061 const scoped_refptr<VaapiDecodeSurface>& dec_surface) { |
| 1061 if (!vaapi_wrapper_->ExecuteAndDestroyPendingBuffers( | 1062 if (!vaapi_wrapper_->ExecuteAndDestroyPendingBuffers( |
| 1062 dec_surface->va_surface()->id())) { | 1063 dec_surface->va_surface()->id())) { |
| 1063 DVLOG(1) << "Failed decoding picture"; | 1064 DVLOG(1) << "Failed decoding picture"; |
| 1064 return false; | 1065 return false; |
| 1065 } | 1066 } |
| 1066 | 1067 |
| 1067 return true; | 1068 return true; |
| 1068 } | 1069 } |
| 1069 | 1070 |
| 1070 void VaapiVideoDecodeAccelerator::SurfaceReady( | 1071 void VaapiVideoDecodeAccelerator::SurfaceReady( |
| 1071 const scoped_refptr<VaapiDecodeSurface>& dec_surface) { | 1072 const scoped_refptr<VaapiDecodeSurface>& dec_surface) { |
| 1072 if (message_loop_ != base::MessageLoop::current()) { | 1073 if (!task_runner_->BelongsToCurrentThread()) { |
| 1073 message_loop_->PostTask( | 1074 task_runner_->PostTask( |
| 1074 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::SurfaceReady, | 1075 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::SurfaceReady, |
| 1075 weak_this_, dec_surface)); | 1076 weak_this_, dec_surface)); |
| 1076 return; | 1077 return; |
| 1077 } | 1078 } |
| 1078 | 1079 |
| 1079 DCHECK(!awaiting_va_surfaces_recycle_); | 1080 DCHECK(!awaiting_va_surfaces_recycle_); |
| 1080 | 1081 |
| 1081 { | 1082 { |
| 1082 base::AutoLock auto_lock(lock_); | 1083 base::AutoLock auto_lock(lock_); |
| 1083 // Drop any requests to output if we are resetting or being destroyed. | 1084 // 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... |
| 1825 return vaapi_pic->dec_surface(); | 1826 return vaapi_pic->dec_surface(); |
| 1826 } | 1827 } |
| 1827 | 1828 |
| 1828 // static | 1829 // static |
| 1829 VideoDecodeAccelerator::SupportedProfiles | 1830 VideoDecodeAccelerator::SupportedProfiles |
| 1830 VaapiVideoDecodeAccelerator::GetSupportedProfiles() { | 1831 VaapiVideoDecodeAccelerator::GetSupportedProfiles() { |
| 1831 return VaapiWrapper::GetSupportedDecodeProfiles(); | 1832 return VaapiWrapper::GetSupportedDecodeProfiles(); |
| 1832 } | 1833 } |
| 1833 | 1834 |
| 1834 } // namespace media | 1835 } // namespace media |
| OLD | NEW |