| 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 |