| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 <fcntl.h> | 5 #include <fcntl.h> |
| 6 #include <linux/videodev2.h> | 6 #include <linux/videodev2.h> |
| 7 #include <poll.h> | 7 #include <poll.h> |
| 8 #include <sys/eventfd.h> | 8 #include <sys/eventfd.h> |
| 9 #include <sys/ioctl.h> | 9 #include <sys/ioctl.h> |
| 10 #include <sys/mman.h> | 10 #include <sys/mman.h> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/bind_helpers.h" | 13 #include "base/bind_helpers.h" |
| 14 #include "base/callback.h" | 14 #include "base/callback.h" |
| 15 #include "base/callback_helpers.h" | 15 #include "base/callback_helpers.h" |
| 16 #include "base/command_line.h" | 16 #include "base/command_line.h" |
| 17 #include "base/message_loop/message_loop_proxy.h" | |
| 18 #include "base/numerics/safe_conversions.h" | 17 #include "base/numerics/safe_conversions.h" |
| 19 #include "base/strings/stringprintf.h" | 18 #include "base/strings/stringprintf.h" |
| 20 #include "content/common/gpu/media/v4l2_slice_video_decode_accelerator.h" | 19 #include "content/common/gpu/media/v4l2_slice_video_decode_accelerator.h" |
| 21 #include "media/base/bind_to_current_loop.h" | 20 #include "media/base/bind_to_current_loop.h" |
| 22 #include "media/base/media_switches.h" | 21 #include "media/base/media_switches.h" |
| 23 #include "ui/gl/scoped_binders.h" | 22 #include "ui/gl/scoped_binders.h" |
| 24 | 23 |
| 25 #define LOGF(level) LOG(level) << __FUNCTION__ << "(): " | 24 #define LOGF(level) LOG(level) << __FUNCTION__ << "(): " |
| 26 #define DVLOGF(level) DVLOG(level) << __FUNCTION__ << "(): " | 25 #define DVLOGF(level) DVLOG(level) << __FUNCTION__ << "(): " |
| 27 | 26 |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 at_client(false), | 154 at_client(false), |
| 156 picture_id(-1), | 155 picture_id(-1), |
| 157 egl_image(EGL_NO_IMAGE_KHR), | 156 egl_image(EGL_NO_IMAGE_KHR), |
| 158 egl_sync(EGL_NO_SYNC_KHR), | 157 egl_sync(EGL_NO_SYNC_KHR), |
| 159 cleared(false) { | 158 cleared(false) { |
| 160 } | 159 } |
| 161 | 160 |
| 162 struct V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef { | 161 struct V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef { |
| 163 BitstreamBufferRef( | 162 BitstreamBufferRef( |
| 164 base::WeakPtr<VideoDecodeAccelerator::Client>& client, | 163 base::WeakPtr<VideoDecodeAccelerator::Client>& client, |
| 165 const scoped_refptr<base::MessageLoopProxy>& client_message_loop_proxy, | 164 const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, |
| 166 base::SharedMemory* shm, | 165 base::SharedMemory* shm, |
| 167 size_t size, | 166 size_t size, |
| 168 int32 input_id); | 167 int32 input_id); |
| 169 ~BitstreamBufferRef(); | 168 ~BitstreamBufferRef(); |
| 170 const base::WeakPtr<VideoDecodeAccelerator::Client> client; | 169 const base::WeakPtr<VideoDecodeAccelerator::Client> client; |
| 171 const scoped_refptr<base::MessageLoopProxy> client_message_loop_proxy; | 170 const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner; |
| 172 const scoped_ptr<base::SharedMemory> shm; | 171 const scoped_ptr<base::SharedMemory> shm; |
| 173 const size_t size; | 172 const size_t size; |
| 174 off_t bytes_used; | 173 off_t bytes_used; |
| 175 const int32 input_id; | 174 const int32 input_id; |
| 176 }; | 175 }; |
| 177 | 176 |
| 178 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef( | 177 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef( |
| 179 base::WeakPtr<VideoDecodeAccelerator::Client>& client, | 178 base::WeakPtr<VideoDecodeAccelerator::Client>& client, |
| 180 const scoped_refptr<base::MessageLoopProxy>& client_message_loop_proxy, | 179 const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, |
| 181 base::SharedMemory* shm, | 180 base::SharedMemory* shm, |
| 182 size_t size, | 181 size_t size, |
| 183 int32 input_id) | 182 int32 input_id) |
| 184 : client(client), | 183 : client(client), |
| 185 client_message_loop_proxy(client_message_loop_proxy), | 184 client_task_runner(client_task_runner), |
| 186 shm(shm), | 185 shm(shm), |
| 187 size(size), | 186 size(size), |
| 188 bytes_used(0), | 187 bytes_used(0), |
| 189 input_id(input_id) { | 188 input_id(input_id) { |
| 190 } | 189 } |
| 191 | 190 |
| 192 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() { | 191 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() { |
| 193 if (input_id >= 0) { | 192 if (input_id >= 0) { |
| 194 DVLOGF(5) << "returning input_id: " << input_id; | 193 DVLOGF(5) << "returning input_id: " << input_id; |
| 195 client_message_loop_proxy->PostTask( | 194 client_task_runner->PostTask( |
| 196 FROM_HERE, | 195 FROM_HERE, |
| 197 base::Bind(&VideoDecodeAccelerator::Client::NotifyEndOfBitstreamBuffer, | 196 base::Bind(&VideoDecodeAccelerator::Client::NotifyEndOfBitstreamBuffer, |
| 198 client, input_id)); | 197 client, input_id)); |
| 199 } | 198 } |
| 200 } | 199 } |
| 201 | 200 |
| 202 struct V4L2SliceVideoDecodeAccelerator::EGLSyncKHRRef { | 201 struct V4L2SliceVideoDecodeAccelerator::EGLSyncKHRRef { |
| 203 EGLSyncKHRRef(EGLDisplay egl_display, EGLSyncKHR egl_sync); | 202 EGLSyncKHRRef(EGLDisplay egl_display, EGLSyncKHR egl_sync); |
| 204 ~EGLSyncKHRRef(); | 203 ~EGLSyncKHRRef(); |
| 205 EGLDisplay const egl_display; | 204 EGLDisplay const egl_display; |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 373 | 372 |
| 374 V4L2VP8Picture::~V4L2VP8Picture() { | 373 V4L2VP8Picture::~V4L2VP8Picture() { |
| 375 } | 374 } |
| 376 | 375 |
| 377 V4L2SliceVideoDecodeAccelerator::V4L2SliceVideoDecodeAccelerator( | 376 V4L2SliceVideoDecodeAccelerator::V4L2SliceVideoDecodeAccelerator( |
| 378 const scoped_refptr<V4L2Device>& device, | 377 const scoped_refptr<V4L2Device>& device, |
| 379 EGLDisplay egl_display, | 378 EGLDisplay egl_display, |
| 380 EGLContext egl_context, | 379 EGLContext egl_context, |
| 381 const base::WeakPtr<Client>& io_client, | 380 const base::WeakPtr<Client>& io_client, |
| 382 const base::Callback<bool(void)>& make_context_current, | 381 const base::Callback<bool(void)>& make_context_current, |
| 383 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy) | 382 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) |
| 384 : input_planes_count_(0), | 383 : input_planes_count_(0), |
| 385 output_planes_count_(0), | 384 output_planes_count_(0), |
| 386 child_message_loop_proxy_(base::MessageLoopProxy::current()), | 385 child_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 387 io_message_loop_proxy_(io_message_loop_proxy), | 386 io_task_runner_(io_task_runner), |
| 388 io_client_(io_client), | 387 io_client_(io_client), |
| 389 device_(device), | 388 device_(device), |
| 390 decoder_thread_("V4L2SliceVideoDecodeAcceleratorThread"), | 389 decoder_thread_("V4L2SliceVideoDecodeAcceleratorThread"), |
| 391 device_poll_thread_("V4L2SliceVideoDecodeAcceleratorDevicePollThread"), | 390 device_poll_thread_("V4L2SliceVideoDecodeAcceleratorDevicePollThread"), |
| 392 input_streamon_(false), | 391 input_streamon_(false), |
| 393 input_buffer_queued_count_(0), | 392 input_buffer_queued_count_(0), |
| 394 output_streamon_(false), | 393 output_streamon_(false), |
| 395 output_buffer_queued_count_(0), | 394 output_buffer_queued_count_(0), |
| 396 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN), | 395 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN), |
| 397 output_format_fourcc_(0), | 396 output_format_fourcc_(0), |
| 398 state_(kUninitialized), | 397 state_(kUninitialized), |
| 399 decoder_flushing_(false), | 398 decoder_flushing_(false), |
| 400 decoder_resetting_(false), | 399 decoder_resetting_(false), |
| 401 surface_set_change_pending_(false), | 400 surface_set_change_pending_(false), |
| 402 picture_clearing_count_(0), | 401 picture_clearing_count_(0), |
| 403 pictures_assigned_(false, false), | 402 pictures_assigned_(false, false), |
| 404 make_context_current_(make_context_current), | 403 make_context_current_(make_context_current), |
| 405 egl_display_(egl_display), | 404 egl_display_(egl_display), |
| 406 egl_context_(egl_context), | 405 egl_context_(egl_context), |
| 407 weak_this_factory_(this) { | 406 weak_this_factory_(this) { |
| 408 weak_this_ = weak_this_factory_.GetWeakPtr(); | 407 weak_this_ = weak_this_factory_.GetWeakPtr(); |
| 409 } | 408 } |
| 410 | 409 |
| 411 V4L2SliceVideoDecodeAccelerator::~V4L2SliceVideoDecodeAccelerator() { | 410 V4L2SliceVideoDecodeAccelerator::~V4L2SliceVideoDecodeAccelerator() { |
| 412 DVLOGF(2); | 411 DVLOGF(2); |
| 413 | 412 |
| 414 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 413 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 415 DCHECK(!decoder_thread_.IsRunning()); | 414 DCHECK(!decoder_thread_.IsRunning()); |
| 416 DCHECK(!device_poll_thread_.IsRunning()); | 415 DCHECK(!device_poll_thread_.IsRunning()); |
| 417 | 416 |
| 418 DCHECK(input_buffer_map_.empty()); | 417 DCHECK(input_buffer_map_.empty()); |
| 419 DCHECK(output_buffer_map_.empty()); | 418 DCHECK(output_buffer_map_.empty()); |
| 420 } | 419 } |
| 421 | 420 |
| 422 void V4L2SliceVideoDecodeAccelerator::NotifyError(Error error) { | 421 void V4L2SliceVideoDecodeAccelerator::NotifyError(Error error) { |
| 423 if (!child_message_loop_proxy_->BelongsToCurrentThread()) { | 422 if (!child_task_runner_->BelongsToCurrentThread()) { |
| 424 child_message_loop_proxy_->PostTask( | 423 child_task_runner_->PostTask( |
| 425 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::NotifyError, | 424 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::NotifyError, |
| 426 weak_this_, error)); | 425 weak_this_, error)); |
| 427 return; | 426 return; |
| 428 } | 427 } |
| 429 | 428 |
| 430 if (client_) { | 429 if (client_) { |
| 431 client_->NotifyError(error); | 430 client_->NotifyError(error); |
| 432 client_ptr_factory_.reset(); | 431 client_ptr_factory_.reset(); |
| 433 } | 432 } |
| 434 } | 433 } |
| 435 | 434 |
| 436 bool V4L2SliceVideoDecodeAccelerator::Initialize( | 435 bool V4L2SliceVideoDecodeAccelerator::Initialize( |
| 437 media::VideoCodecProfile profile, | 436 media::VideoCodecProfile profile, |
| 438 VideoDecodeAccelerator::Client* client) { | 437 VideoDecodeAccelerator::Client* client) { |
| 439 DVLOGF(3) << "profile: " << profile; | 438 DVLOGF(3) << "profile: " << profile; |
| 440 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 439 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 441 DCHECK_EQ(state_, kUninitialized); | 440 DCHECK_EQ(state_, kUninitialized); |
| 442 | 441 |
| 443 client_ptr_factory_.reset( | 442 client_ptr_factory_.reset( |
| 444 new base::WeakPtrFactory<VideoDecodeAccelerator::Client>(client)); | 443 new base::WeakPtrFactory<VideoDecodeAccelerator::Client>(client)); |
| 445 client_ = client_ptr_factory_->GetWeakPtr(); | 444 client_ = client_ptr_factory_->GetWeakPtr(); |
| 446 | 445 |
| 447 video_profile_ = profile; | 446 video_profile_ = profile; |
| 448 | 447 |
| 449 if (video_profile_ >= media::H264PROFILE_MIN && | 448 if (video_profile_ >= media::H264PROFILE_MIN && |
| 450 video_profile_ <= media::H264PROFILE_MAX) { | 449 video_profile_ <= media::H264PROFILE_MAX) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 return false; | 491 return false; |
| 493 } | 492 } |
| 494 | 493 |
| 495 if (!SetupFormats()) | 494 if (!SetupFormats()) |
| 496 return false; | 495 return false; |
| 497 | 496 |
| 498 if (!decoder_thread_.Start()) { | 497 if (!decoder_thread_.Start()) { |
| 499 DLOG(ERROR) << "Initialize(): device thread failed to start"; | 498 DLOG(ERROR) << "Initialize(): device thread failed to start"; |
| 500 return false; | 499 return false; |
| 501 } | 500 } |
| 502 decoder_thread_proxy_ = decoder_thread_.message_loop_proxy(); | 501 decoder_thread_task_runner_ = decoder_thread_.task_runner(); |
| 503 | 502 |
| 504 state_ = kInitialized; | 503 state_ = kInitialized; |
| 505 | 504 |
| 506 // InitializeTask will NOTIFY_ERROR on failure. | 505 // InitializeTask will NOTIFY_ERROR on failure. |
| 507 decoder_thread_proxy_->PostTask( | 506 decoder_thread_task_runner_->PostTask( |
| 508 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::InitializeTask, | 507 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::InitializeTask, |
| 509 base::Unretained(this))); | 508 base::Unretained(this))); |
| 510 | 509 |
| 511 DVLOGF(1) << "V4L2SliceVideoDecodeAccelerator initialized"; | 510 DVLOGF(1) << "V4L2SliceVideoDecodeAccelerator initialized"; |
| 512 return true; | 511 return true; |
| 513 } | 512 } |
| 514 | 513 |
| 515 void V4L2SliceVideoDecodeAccelerator::InitializeTask() { | 514 void V4L2SliceVideoDecodeAccelerator::InitializeTask() { |
| 516 DVLOGF(3); | 515 DVLOGF(3); |
| 517 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 516 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 518 DCHECK_EQ(state_, kInitialized); | 517 DCHECK_EQ(state_, kInitialized); |
| 519 | 518 |
| 520 if (!CreateInputBuffers()) | 519 if (!CreateInputBuffers()) |
| 521 NOTIFY_ERROR(PLATFORM_FAILURE); | 520 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 522 | 521 |
| 523 // Output buffers will be created once decoder gives us information | 522 // Output buffers will be created once decoder gives us information |
| 524 // about their size and required count. | 523 // about their size and required count. |
| 525 state_ = kDecoding; | 524 state_ = kDecoding; |
| 526 } | 525 } |
| 527 | 526 |
| 528 void V4L2SliceVideoDecodeAccelerator::Destroy() { | 527 void V4L2SliceVideoDecodeAccelerator::Destroy() { |
| 529 DVLOGF(3); | 528 DVLOGF(3); |
| 530 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 529 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 531 | 530 |
| 532 if (decoder_thread_.IsRunning()) { | 531 if (decoder_thread_.IsRunning()) { |
| 533 decoder_thread_proxy_->PostTask( | 532 decoder_thread_task_runner_->PostTask( |
| 534 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DestroyTask, | 533 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DestroyTask, |
| 535 base::Unretained(this))); | 534 base::Unretained(this))); |
| 536 | 535 |
| 537 // Wait for tasks to finish/early-exit. | 536 // Wait for tasks to finish/early-exit. |
| 538 decoder_thread_.Stop(); | 537 decoder_thread_.Stop(); |
| 539 } | 538 } |
| 540 | 539 |
| 541 delete this; | 540 delete this; |
| 542 DVLOGF(3) << "Destroyed"; | 541 DVLOGF(3) << "Destroyed"; |
| 543 } | 542 } |
| 544 | 543 |
| 545 void V4L2SliceVideoDecodeAccelerator::DestroyTask() { | 544 void V4L2SliceVideoDecodeAccelerator::DestroyTask() { |
| 546 DVLOGF(3); | 545 DVLOGF(3); |
| 547 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 546 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 548 | 547 |
| 549 state_ = kError; | 548 state_ = kError; |
| 550 | 549 |
| 551 decoder_->Reset(); | 550 decoder_->Reset(); |
| 552 | 551 |
| 553 decoder_current_bitstream_buffer_.reset(); | 552 decoder_current_bitstream_buffer_.reset(); |
| 554 while (!decoder_input_queue_.empty()) | 553 while (!decoder_input_queue_.empty()) |
| 555 decoder_input_queue_.pop(); | 554 decoder_input_queue_.pop(); |
| 556 | 555 |
| 557 // Stop streaming and the device_poll_thread_. | 556 // Stop streaming and the device_poll_thread_. |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 618 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 617 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 619 format.fmt.pix_mp.pixelformat = output_format_fourcc_; | 618 format.fmt.pix_mp.pixelformat = output_format_fourcc_; |
| 620 format.fmt.pix_mp.num_planes = output_planes_count_; | 619 format.fmt.pix_mp.num_planes = output_planes_count_; |
| 621 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format); | 620 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format); |
| 622 | 621 |
| 623 return true; | 622 return true; |
| 624 } | 623 } |
| 625 | 624 |
| 626 bool V4L2SliceVideoDecodeAccelerator::CreateInputBuffers() { | 625 bool V4L2SliceVideoDecodeAccelerator::CreateInputBuffers() { |
| 627 DVLOGF(3); | 626 DVLOGF(3); |
| 628 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 627 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 629 DCHECK(!input_streamon_); | 628 DCHECK(!input_streamon_); |
| 630 DCHECK(input_buffer_map_.empty()); | 629 DCHECK(input_buffer_map_.empty()); |
| 631 | 630 |
| 632 struct v4l2_requestbuffers reqbufs; | 631 struct v4l2_requestbuffers reqbufs; |
| 633 memset(&reqbufs, 0, sizeof(reqbufs)); | 632 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 634 reqbufs.count = kNumInputBuffers; | 633 reqbufs.count = kNumInputBuffers; |
| 635 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 634 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 636 reqbufs.memory = V4L2_MEMORY_MMAP; | 635 reqbufs.memory = V4L2_MEMORY_MMAP; |
| 637 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); | 636 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); |
| 638 if (reqbufs.count < kNumInputBuffers) { | 637 if (reqbufs.count < kNumInputBuffers) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 665 } | 664 } |
| 666 input_buffer_map_[i].address = address; | 665 input_buffer_map_[i].address = address; |
| 667 input_buffer_map_[i].length = buffer.m.planes[0].length; | 666 input_buffer_map_[i].length = buffer.m.planes[0].length; |
| 668 } | 667 } |
| 669 | 668 |
| 670 return true; | 669 return true; |
| 671 } | 670 } |
| 672 | 671 |
| 673 bool V4L2SliceVideoDecodeAccelerator::CreateOutputBuffers() { | 672 bool V4L2SliceVideoDecodeAccelerator::CreateOutputBuffers() { |
| 674 DVLOGF(3); | 673 DVLOGF(3); |
| 675 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 674 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 676 DCHECK(!output_streamon_); | 675 DCHECK(!output_streamon_); |
| 677 DCHECK(output_buffer_map_.empty()); | 676 DCHECK(output_buffer_map_.empty()); |
| 678 DCHECK(surfaces_at_display_.empty()); | 677 DCHECK(surfaces_at_display_.empty()); |
| 679 DCHECK(surfaces_at_device_.empty()); | 678 DCHECK(surfaces_at_device_.empty()); |
| 680 | 679 |
| 681 visible_size_ = decoder_->GetPicSize(); | 680 visible_size_ = decoder_->GetPicSize(); |
| 682 size_t num_pictures = decoder_->GetRequiredNumOfPictures(); | 681 size_t num_pictures = decoder_->GetRequiredNumOfPictures(); |
| 683 | 682 |
| 684 DCHECK_GT(num_pictures, 0u); | 683 DCHECK_GT(num_pictures, 0u); |
| 685 DCHECK(!visible_size_.IsEmpty()); | 684 DCHECK(!visible_size_.IsEmpty()); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 719 PLOG(ERROR) << "Could not allocate enough output buffers"; | 718 PLOG(ERROR) << "Could not allocate enough output buffers"; |
| 720 return false; | 719 return false; |
| 721 } | 720 } |
| 722 | 721 |
| 723 output_buffer_map_.resize(reqbufs.count); | 722 output_buffer_map_.resize(reqbufs.count); |
| 724 | 723 |
| 725 DVLOGF(3) << "buffer_count=" << output_buffer_map_.size() | 724 DVLOGF(3) << "buffer_count=" << output_buffer_map_.size() |
| 726 << ", visible size=" << visible_size_.ToString() | 725 << ", visible size=" << visible_size_.ToString() |
| 727 << ", coded size=" << coded_size_.ToString(); | 726 << ", coded size=" << coded_size_.ToString(); |
| 728 | 727 |
| 729 child_message_loop_proxy_->PostTask( | 728 child_task_runner_->PostTask( |
| 730 FROM_HERE, | 729 FROM_HERE, |
| 731 base::Bind(&VideoDecodeAccelerator::Client::ProvidePictureBuffers, | 730 base::Bind(&VideoDecodeAccelerator::Client::ProvidePictureBuffers, |
| 732 client_, output_buffer_map_.size(), coded_size_, | 731 client_, output_buffer_map_.size(), coded_size_, |
| 733 device_->GetTextureTarget())); | 732 device_->GetTextureTarget())); |
| 734 | 733 |
| 735 // Wait for the client to call AssignPictureBuffers() on the Child thread. | 734 // Wait for the client to call AssignPictureBuffers() on the Child thread. |
| 736 // We do this, because if we continue decoding without finishing buffer | 735 // We do this, because if we continue decoding without finishing buffer |
| 737 // allocation, we may end up Resetting before AssignPictureBuffers arrives, | 736 // allocation, we may end up Resetting before AssignPictureBuffers arrives, |
| 738 // resulting in unnecessary complications and subtle bugs. | 737 // resulting in unnecessary complications and subtle bugs. |
| 739 pictures_assigned_.Wait(); | 738 pictures_assigned_.Wait(); |
| 740 | 739 |
| 741 return true; | 740 return true; |
| 742 } | 741 } |
| 743 | 742 |
| 744 void V4L2SliceVideoDecodeAccelerator::DestroyInputBuffers() { | 743 void V4L2SliceVideoDecodeAccelerator::DestroyInputBuffers() { |
| 745 DVLOGF(3); | 744 DVLOGF(3); |
| 746 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread() || | 745 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread() || |
| 747 !decoder_thread_.IsRunning()); | 746 !decoder_thread_.IsRunning()); |
| 748 DCHECK(!input_streamon_); | 747 DCHECK(!input_streamon_); |
| 749 | 748 |
| 750 for (auto& input_record : input_buffer_map_) { | 749 for (auto& input_record : input_buffer_map_) { |
| 751 if (input_record.address != nullptr) | 750 if (input_record.address != nullptr) |
| 752 device_->Munmap(input_record.address, input_record.length); | 751 device_->Munmap(input_record.address, input_record.length); |
| 753 } | 752 } |
| 754 | 753 |
| 755 struct v4l2_requestbuffers reqbufs; | 754 struct v4l2_requestbuffers reqbufs; |
| 756 memset(&reqbufs, 0, sizeof(reqbufs)); | 755 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 757 reqbufs.count = 0; | 756 reqbufs.count = 0; |
| 758 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 757 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 759 reqbufs.memory = V4L2_MEMORY_MMAP; | 758 reqbufs.memory = V4L2_MEMORY_MMAP; |
| 760 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); | 759 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); |
| 761 | 760 |
| 762 input_buffer_map_.clear(); | 761 input_buffer_map_.clear(); |
| 763 free_input_buffers_.clear(); | 762 free_input_buffers_.clear(); |
| 764 } | 763 } |
| 765 | 764 |
| 766 void V4L2SliceVideoDecodeAccelerator::DismissPictures( | 765 void V4L2SliceVideoDecodeAccelerator::DismissPictures( |
| 767 std::vector<int32> picture_buffer_ids, | 766 std::vector<int32> picture_buffer_ids, |
| 768 base::WaitableEvent* done) { | 767 base::WaitableEvent* done) { |
| 769 DVLOGF(3); | 768 DVLOGF(3); |
| 770 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 769 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 771 | 770 |
| 772 for (auto picture_buffer_id : picture_buffer_ids) { | 771 for (auto picture_buffer_id : picture_buffer_ids) { |
| 773 DVLOGF(1) << "dismissing PictureBuffer id=" << picture_buffer_id; | 772 DVLOGF(1) << "dismissing PictureBuffer id=" << picture_buffer_id; |
| 774 client_->DismissPictureBuffer(picture_buffer_id); | 773 client_->DismissPictureBuffer(picture_buffer_id); |
| 775 } | 774 } |
| 776 | 775 |
| 777 done->Signal(); | 776 done->Signal(); |
| 778 } | 777 } |
| 779 | 778 |
| 780 void V4L2SliceVideoDecodeAccelerator::DevicePollTask(bool poll_device) { | 779 void V4L2SliceVideoDecodeAccelerator::DevicePollTask(bool poll_device) { |
| 781 DVLOGF(4); | 780 DVLOGF(4); |
| 782 DCHECK_EQ(device_poll_thread_.message_loop(), base::MessageLoop::current()); | 781 DCHECK_EQ(device_poll_thread_.message_loop(), base::MessageLoop::current()); |
| 783 | 782 |
| 784 bool event_pending; | 783 bool event_pending; |
| 785 if (!device_->Poll(poll_device, &event_pending)) { | 784 if (!device_->Poll(poll_device, &event_pending)) { |
| 786 NOTIFY_ERROR(PLATFORM_FAILURE); | 785 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 787 return; | 786 return; |
| 788 } | 787 } |
| 789 | 788 |
| 790 // All processing should happen on ServiceDeviceTask(), since we shouldn't | 789 // All processing should happen on ServiceDeviceTask(), since we shouldn't |
| 791 // touch encoder state from this thread. | 790 // touch encoder state from this thread. |
| 792 decoder_thread_proxy_->PostTask( | 791 decoder_thread_task_runner_->PostTask( |
| 793 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::ServiceDeviceTask, | 792 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::ServiceDeviceTask, |
| 794 base::Unretained(this))); | 793 base::Unretained(this))); |
| 795 } | 794 } |
| 796 | 795 |
| 797 void V4L2SliceVideoDecodeAccelerator::ServiceDeviceTask() { | 796 void V4L2SliceVideoDecodeAccelerator::ServiceDeviceTask() { |
| 798 DVLOGF(4); | 797 DVLOGF(4); |
| 799 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 798 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 800 | 799 |
| 801 // ServiceDeviceTask() should only ever be scheduled from DevicePollTask(). | 800 // ServiceDeviceTask() should only ever be scheduled from DevicePollTask(). |
| 802 | 801 |
| 803 Dequeue(); | 802 Dequeue(); |
| 804 SchedulePollIfNeeded(); | 803 SchedulePollIfNeeded(); |
| 805 } | 804 } |
| 806 | 805 |
| 807 void V4L2SliceVideoDecodeAccelerator::SchedulePollIfNeeded() { | 806 void V4L2SliceVideoDecodeAccelerator::SchedulePollIfNeeded() { |
| 808 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 807 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 809 | 808 |
| 810 if (!device_poll_thread_.IsRunning()) { | 809 if (!device_poll_thread_.IsRunning()) { |
| 811 DVLOGF(2) << "Device poll thread stopped, will not schedule poll"; | 810 DVLOGF(2) << "Device poll thread stopped, will not schedule poll"; |
| 812 return; | 811 return; |
| 813 } | 812 } |
| 814 | 813 |
| 815 DCHECK(input_streamon_ || output_streamon_); | 814 DCHECK(input_streamon_ || output_streamon_); |
| 816 | 815 |
| 817 if (input_buffer_queued_count_ + output_buffer_queued_count_ == 0) { | 816 if (input_buffer_queued_count_ + output_buffer_queued_count_ == 0) { |
| 818 DVLOGF(4) << "No buffers queued, will not schedule poll"; | 817 DVLOGF(4) << "No buffers queued, will not schedule poll"; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 833 << input_buffer_map_.size() << "]->[" | 832 << input_buffer_map_.size() << "]->[" |
| 834 << free_output_buffers_.size() << "+" | 833 << free_output_buffers_.size() << "+" |
| 835 << output_buffer_queued_count_ << "/" | 834 << output_buffer_queued_count_ << "/" |
| 836 << output_buffer_map_.size() << "]" | 835 << output_buffer_map_.size() << "]" |
| 837 << " => DISPLAYQ[" << decoder_display_queue_.size() << "]" | 836 << " => DISPLAYQ[" << decoder_display_queue_.size() << "]" |
| 838 << " => CLIENT[" << surfaces_at_display_.size() << "]"; | 837 << " => CLIENT[" << surfaces_at_display_.size() << "]"; |
| 839 } | 838 } |
| 840 | 839 |
| 841 void V4L2SliceVideoDecodeAccelerator::Enqueue( | 840 void V4L2SliceVideoDecodeAccelerator::Enqueue( |
| 842 const scoped_refptr<V4L2DecodeSurface>& dec_surface) { | 841 const scoped_refptr<V4L2DecodeSurface>& dec_surface) { |
| 843 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 842 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 844 | 843 |
| 845 const int old_inputs_queued = input_buffer_queued_count_; | 844 const int old_inputs_queued = input_buffer_queued_count_; |
| 846 const int old_outputs_queued = output_buffer_queued_count_; | 845 const int old_outputs_queued = output_buffer_queued_count_; |
| 847 | 846 |
| 848 if (!EnqueueInputRecord(dec_surface->input_record(), | 847 if (!EnqueueInputRecord(dec_surface->input_record(), |
| 849 dec_surface->config_store())) { | 848 dec_surface->config_store())) { |
| 850 DVLOGF(1) << "Failed queueing an input buffer"; | 849 DVLOGF(1) << "Failed queueing an input buffer"; |
| 851 NOTIFY_ERROR(PLATFORM_FAILURE); | 850 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 852 return; | 851 return; |
| 853 } | 852 } |
| 854 | 853 |
| 855 if (!EnqueueOutputRecord(dec_surface->output_record())) { | 854 if (!EnqueueOutputRecord(dec_surface->output_record())) { |
| 856 DVLOGF(1) << "Failed queueing an output buffer"; | 855 DVLOGF(1) << "Failed queueing an output buffer"; |
| 857 NOTIFY_ERROR(PLATFORM_FAILURE); | 856 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 858 return; | 857 return; |
| 859 } | 858 } |
| 860 | 859 |
| 861 bool inserted = | 860 bool inserted = |
| 862 surfaces_at_device_.insert(std::make_pair(dec_surface->output_record(), | 861 surfaces_at_device_.insert(std::make_pair(dec_surface->output_record(), |
| 863 dec_surface)).second; | 862 dec_surface)).second; |
| 864 DCHECK(inserted); | 863 DCHECK(inserted); |
| 865 | 864 |
| 866 if (old_inputs_queued == 0 && old_outputs_queued == 0) | 865 if (old_inputs_queued == 0 && old_outputs_queued == 0) |
| 867 SchedulePollIfNeeded(); | 866 SchedulePollIfNeeded(); |
| 868 } | 867 } |
| 869 | 868 |
| 870 void V4L2SliceVideoDecodeAccelerator::Dequeue() { | 869 void V4L2SliceVideoDecodeAccelerator::Dequeue() { |
| 871 DVLOGF(3); | 870 DVLOGF(3); |
| 872 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 871 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 873 | 872 |
| 874 struct v4l2_buffer dqbuf; | 873 struct v4l2_buffer dqbuf; |
| 875 struct v4l2_plane planes[VIDEO_MAX_PLANES]; | 874 struct v4l2_plane planes[VIDEO_MAX_PLANES]; |
| 876 while (input_buffer_queued_count_ > 0) { | 875 while (input_buffer_queued_count_ > 0) { |
| 877 DCHECK(input_streamon_); | 876 DCHECK(input_streamon_); |
| 878 memset(&dqbuf, 0, sizeof(dqbuf)); | 877 memset(&dqbuf, 0, sizeof(dqbuf)); |
| 879 memset(&planes, 0, sizeof(planes)); | 878 memset(&planes, 0, sizeof(planes)); |
| 880 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 879 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 881 dqbuf.memory = V4L2_MEMORY_USERPTR; | 880 dqbuf.memory = V4L2_MEMORY_USERPTR; |
| 882 dqbuf.m.planes = planes; | 881 dqbuf.m.planes = planes; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 947 // put the decoder in an undefined state. | 946 // put the decoder in an undefined state. |
| 948 FinishSurfaceSetChangeIfNeeded(); | 947 FinishSurfaceSetChangeIfNeeded(); |
| 949 | 948 |
| 950 // Process external (client) requests. | 949 // Process external (client) requests. |
| 951 FinishFlushIfNeeded(); | 950 FinishFlushIfNeeded(); |
| 952 FinishResetIfNeeded(); | 951 FinishResetIfNeeded(); |
| 953 } | 952 } |
| 954 | 953 |
| 955 void V4L2SliceVideoDecodeAccelerator::ReuseInputBuffer(int index) { | 954 void V4L2SliceVideoDecodeAccelerator::ReuseInputBuffer(int index) { |
| 956 DVLOGF(4) << "Reusing input buffer, index=" << index; | 955 DVLOGF(4) << "Reusing input buffer, index=" << index; |
| 957 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 956 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 958 | 957 |
| 959 DCHECK_LT(index, static_cast<int>(input_buffer_map_.size())); | 958 DCHECK_LT(index, static_cast<int>(input_buffer_map_.size())); |
| 960 InputRecord& input_record = input_buffer_map_[index]; | 959 InputRecord& input_record = input_buffer_map_[index]; |
| 961 | 960 |
| 962 DCHECK(!input_record.at_device); | 961 DCHECK(!input_record.at_device); |
| 963 input_record.input_id = -1; | 962 input_record.input_id = -1; |
| 964 input_record.bytes_used = 0; | 963 input_record.bytes_used = 0; |
| 965 | 964 |
| 966 DCHECK_EQ(std::count(free_input_buffers_.begin(), free_input_buffers_.end(), | 965 DCHECK_EQ(std::count(free_input_buffers_.begin(), free_input_buffers_.end(), |
| 967 index), 0); | 966 index), 0); |
| 968 free_input_buffers_.push_back(index); | 967 free_input_buffers_.push_back(index); |
| 969 } | 968 } |
| 970 | 969 |
| 971 void V4L2SliceVideoDecodeAccelerator::ReuseOutputBuffer(int index) { | 970 void V4L2SliceVideoDecodeAccelerator::ReuseOutputBuffer(int index) { |
| 972 DVLOGF(4) << "Reusing output buffer, index=" << index; | 971 DVLOGF(4) << "Reusing output buffer, index=" << index; |
| 973 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 972 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 974 | 973 |
| 975 DCHECK_LT(index, static_cast<int>(output_buffer_map_.size())); | 974 DCHECK_LT(index, static_cast<int>(output_buffer_map_.size())); |
| 976 OutputRecord& output_record = output_buffer_map_[index]; | 975 OutputRecord& output_record = output_buffer_map_[index]; |
| 977 DCHECK(!output_record.at_device); | 976 DCHECK(!output_record.at_device); |
| 978 DCHECK(!output_record.at_client); | 977 DCHECK(!output_record.at_client); |
| 979 | 978 |
| 980 DCHECK_EQ(std::count(free_output_buffers_.begin(), free_output_buffers_.end(), | 979 DCHECK_EQ(std::count(free_output_buffers_.begin(), free_output_buffers_.end(), |
| 981 index), 0); | 980 index), 0); |
| 982 free_output_buffers_.push_back(index); | 981 free_output_buffers_.push_back(index); |
| 983 | 982 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1055 output_record.at_device = true; | 1054 output_record.at_device = true; |
| 1056 output_buffer_queued_count_++; | 1055 output_buffer_queued_count_++; |
| 1057 DVLOGF(4) << "Enqueued output=" << qbuf.index | 1056 DVLOGF(4) << "Enqueued output=" << qbuf.index |
| 1058 << " count: " << output_buffer_queued_count_; | 1057 << " count: " << output_buffer_queued_count_; |
| 1059 | 1058 |
| 1060 return true; | 1059 return true; |
| 1061 } | 1060 } |
| 1062 | 1061 |
| 1063 bool V4L2SliceVideoDecodeAccelerator::StartDevicePoll() { | 1062 bool V4L2SliceVideoDecodeAccelerator::StartDevicePoll() { |
| 1064 DVLOGF(3) << "Starting device poll"; | 1063 DVLOGF(3) << "Starting device poll"; |
| 1065 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 1064 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1066 DCHECK(!device_poll_thread_.IsRunning()); | 1065 DCHECK(!device_poll_thread_.IsRunning()); |
| 1067 | 1066 |
| 1068 // Start up the device poll thread and schedule its first DevicePollTask(). | 1067 // Start up the device poll thread and schedule its first DevicePollTask(). |
| 1069 if (!device_poll_thread_.Start()) { | 1068 if (!device_poll_thread_.Start()) { |
| 1070 DLOG(ERROR) << "StartDevicePoll(): Device thread failed to start"; | 1069 DLOG(ERROR) << "StartDevicePoll(): Device thread failed to start"; |
| 1071 NOTIFY_ERROR(PLATFORM_FAILURE); | 1070 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1072 return false; | 1071 return false; |
| 1073 } | 1072 } |
| 1074 if (!input_streamon_) { | 1073 if (!input_streamon_) { |
| 1075 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1074 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1086 device_poll_thread_.message_loop()->PostTask( | 1085 device_poll_thread_.message_loop()->PostTask( |
| 1087 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DevicePollTask, | 1086 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DevicePollTask, |
| 1088 base::Unretained(this), true)); | 1087 base::Unretained(this), true)); |
| 1089 | 1088 |
| 1090 return true; | 1089 return true; |
| 1091 } | 1090 } |
| 1092 | 1091 |
| 1093 bool V4L2SliceVideoDecodeAccelerator::StopDevicePoll(bool keep_input_state) { | 1092 bool V4L2SliceVideoDecodeAccelerator::StopDevicePoll(bool keep_input_state) { |
| 1094 DVLOGF(3) << "Stopping device poll"; | 1093 DVLOGF(3) << "Stopping device poll"; |
| 1095 if (decoder_thread_.IsRunning()) | 1094 if (decoder_thread_.IsRunning()) |
| 1096 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 1095 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1097 | 1096 |
| 1098 // Signal the DevicePollTask() to stop, and stop the device poll thread. | 1097 // Signal the DevicePollTask() to stop, and stop the device poll thread. |
| 1099 if (!device_->SetDevicePollInterrupt()) { | 1098 if (!device_->SetDevicePollInterrupt()) { |
| 1100 PLOG(ERROR) << "SetDevicePollInterrupt(): failed"; | 1099 PLOG(ERROR) << "SetDevicePollInterrupt(): failed"; |
| 1101 NOTIFY_ERROR(PLATFORM_FAILURE); | 1100 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1102 return false; | 1101 return false; |
| 1103 } | 1102 } |
| 1104 device_poll_thread_.Stop(); | 1103 device_poll_thread_.Stop(); |
| 1105 DVLOGF(3) << "Device poll thread stopped"; | 1104 DVLOGF(3) << "Device poll thread stopped"; |
| 1106 | 1105 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1154 decoder_display_queue_.pop(); | 1153 decoder_display_queue_.pop(); |
| 1155 | 1154 |
| 1156 DVLOGF(3) << "Device poll stopped"; | 1155 DVLOGF(3) << "Device poll stopped"; |
| 1157 return true; | 1156 return true; |
| 1158 } | 1157 } |
| 1159 | 1158 |
| 1160 void V4L2SliceVideoDecodeAccelerator::Decode( | 1159 void V4L2SliceVideoDecodeAccelerator::Decode( |
| 1161 const media::BitstreamBuffer& bitstream_buffer) { | 1160 const media::BitstreamBuffer& bitstream_buffer) { |
| 1162 DVLOGF(3) << "input_id=" << bitstream_buffer.id() | 1161 DVLOGF(3) << "input_id=" << bitstream_buffer.id() |
| 1163 << ", size=" << bitstream_buffer.size(); | 1162 << ", size=" << bitstream_buffer.size(); |
| 1164 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 1163 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
| 1165 | 1164 |
| 1166 decoder_thread_proxy_->PostTask( | 1165 decoder_thread_task_runner_->PostTask( |
| 1167 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DecodeTask, | 1166 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DecodeTask, |
| 1168 base::Unretained(this), bitstream_buffer)); | 1167 base::Unretained(this), bitstream_buffer)); |
| 1169 } | 1168 } |
| 1170 | 1169 |
| 1171 void V4L2SliceVideoDecodeAccelerator::DecodeTask( | 1170 void V4L2SliceVideoDecodeAccelerator::DecodeTask( |
| 1172 const media::BitstreamBuffer& bitstream_buffer) { | 1171 const media::BitstreamBuffer& bitstream_buffer) { |
| 1173 DVLOGF(3) << "input_id=" << bitstream_buffer.id() | 1172 DVLOGF(3) << "input_id=" << bitstream_buffer.id() |
| 1174 << " size=" << bitstream_buffer.size(); | 1173 << " size=" << bitstream_buffer.size(); |
| 1175 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 1174 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1176 | 1175 |
| 1177 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( | 1176 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( |
| 1178 io_client_, io_message_loop_proxy_, | 1177 io_client_, io_task_runner_, |
| 1179 new base::SharedMemory(bitstream_buffer.handle(), true), | 1178 new base::SharedMemory(bitstream_buffer.handle(), true), |
| 1180 bitstream_buffer.size(), bitstream_buffer.id())); | 1179 bitstream_buffer.size(), bitstream_buffer.id())); |
| 1181 if (!bitstream_record->shm->Map(bitstream_buffer.size())) { | 1180 if (!bitstream_record->shm->Map(bitstream_buffer.size())) { |
| 1182 LOGF(ERROR) << "Could not map bitstream_buffer"; | 1181 LOGF(ERROR) << "Could not map bitstream_buffer"; |
| 1183 NOTIFY_ERROR(UNREADABLE_INPUT); | 1182 NOTIFY_ERROR(UNREADABLE_INPUT); |
| 1184 return; | 1183 return; |
| 1185 } | 1184 } |
| 1186 DVLOGF(3) << "mapped at=" << bitstream_record->shm->memory(); | 1185 DVLOGF(3) << "mapped at=" << bitstream_record->shm->memory(); |
| 1187 | 1186 |
| 1188 decoder_input_queue_.push( | 1187 decoder_input_queue_.push( |
| 1189 linked_ptr<BitstreamBufferRef>(bitstream_record.release())); | 1188 linked_ptr<BitstreamBufferRef>(bitstream_record.release())); |
| 1190 | 1189 |
| 1191 ScheduleDecodeBufferTaskIfNeeded(); | 1190 ScheduleDecodeBufferTaskIfNeeded(); |
| 1192 } | 1191 } |
| 1193 | 1192 |
| 1194 bool V4L2SliceVideoDecodeAccelerator::TrySetNewBistreamBuffer() { | 1193 bool V4L2SliceVideoDecodeAccelerator::TrySetNewBistreamBuffer() { |
| 1195 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 1194 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1196 DCHECK(!decoder_current_bitstream_buffer_); | 1195 DCHECK(!decoder_current_bitstream_buffer_); |
| 1197 | 1196 |
| 1198 if (decoder_input_queue_.empty()) | 1197 if (decoder_input_queue_.empty()) |
| 1199 return false; | 1198 return false; |
| 1200 | 1199 |
| 1201 decoder_current_bitstream_buffer_.reset( | 1200 decoder_current_bitstream_buffer_.reset( |
| 1202 decoder_input_queue_.front().release()); | 1201 decoder_input_queue_.front().release()); |
| 1203 decoder_input_queue_.pop(); | 1202 decoder_input_queue_.pop(); |
| 1204 | 1203 |
| 1205 if (decoder_current_bitstream_buffer_->input_id == kFlushBufferId) { | 1204 if (decoder_current_bitstream_buffer_->input_id == kFlushBufferId) { |
| 1206 // This is a buffer we queued for ourselves to trigger flush at this time. | 1205 // This is a buffer we queued for ourselves to trigger flush at this time. |
| 1207 InitiateFlush(); | 1206 InitiateFlush(); |
| 1208 return false; | 1207 return false; |
| 1209 } | 1208 } |
| 1210 | 1209 |
| 1211 const uint8_t* const data = reinterpret_cast<const uint8_t*>( | 1210 const uint8_t* const data = reinterpret_cast<const uint8_t*>( |
| 1212 decoder_current_bitstream_buffer_->shm->memory()); | 1211 decoder_current_bitstream_buffer_->shm->memory()); |
| 1213 const size_t data_size = decoder_current_bitstream_buffer_->size; | 1212 const size_t data_size = decoder_current_bitstream_buffer_->size; |
| 1214 decoder_->SetStream(data, data_size); | 1213 decoder_->SetStream(data, data_size); |
| 1215 | 1214 |
| 1216 return true; | 1215 return true; |
| 1217 } | 1216 } |
| 1218 | 1217 |
| 1219 void V4L2SliceVideoDecodeAccelerator::ScheduleDecodeBufferTaskIfNeeded() { | 1218 void V4L2SliceVideoDecodeAccelerator::ScheduleDecodeBufferTaskIfNeeded() { |
| 1220 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 1219 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1221 if (state_ == kDecoding) { | 1220 if (state_ == kDecoding) { |
| 1222 decoder_thread_proxy_->PostTask( | 1221 decoder_thread_task_runner_->PostTask( |
| 1223 FROM_HERE, | 1222 FROM_HERE, |
| 1224 base::Bind(&V4L2SliceVideoDecodeAccelerator::DecodeBufferTask, | 1223 base::Bind(&V4L2SliceVideoDecodeAccelerator::DecodeBufferTask, |
| 1225 base::Unretained(this))); | 1224 base::Unretained(this))); |
| 1226 } | 1225 } |
| 1227 } | 1226 } |
| 1228 | 1227 |
| 1229 void V4L2SliceVideoDecodeAccelerator::DecodeBufferTask() { | 1228 void V4L2SliceVideoDecodeAccelerator::DecodeBufferTask() { |
| 1230 DVLOGF(3); | 1229 DVLOGF(3); |
| 1231 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 1230 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1232 | 1231 |
| 1233 if (state_ != kDecoding) { | 1232 if (state_ != kDecoding) { |
| 1234 DVLOGF(3) << "Early exit, not in kDecoding"; | 1233 DVLOGF(3) << "Early exit, not in kDecoding"; |
| 1235 return; | 1234 return; |
| 1236 } | 1235 } |
| 1237 | 1236 |
| 1238 while (true) { | 1237 while (true) { |
| 1239 AcceleratedVideoDecoder::DecodeResult res; | 1238 AcceleratedVideoDecoder::DecodeResult res; |
| 1240 res = decoder_->Decode(); | 1239 res = decoder_->Decode(); |
| 1241 switch (res) { | 1240 switch (res) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1259 case AcceleratedVideoDecoder::kDecodeError: | 1258 case AcceleratedVideoDecoder::kDecodeError: |
| 1260 DVLOGF(1) << "Error decoding stream"; | 1259 DVLOGF(1) << "Error decoding stream"; |
| 1261 NOTIFY_ERROR(PLATFORM_FAILURE); | 1260 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1262 return; | 1261 return; |
| 1263 } | 1262 } |
| 1264 } | 1263 } |
| 1265 } | 1264 } |
| 1266 | 1265 |
| 1267 void V4L2SliceVideoDecodeAccelerator::InitiateSurfaceSetChange() { | 1266 void V4L2SliceVideoDecodeAccelerator::InitiateSurfaceSetChange() { |
| 1268 DVLOGF(2); | 1267 DVLOGF(2); |
| 1269 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 1268 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1270 | 1269 |
| 1271 DCHECK_EQ(state_, kDecoding); | 1270 DCHECK_EQ(state_, kDecoding); |
| 1272 state_ = kIdle; | 1271 state_ = kIdle; |
| 1273 | 1272 |
| 1274 DCHECK(!surface_set_change_pending_); | 1273 DCHECK(!surface_set_change_pending_); |
| 1275 surface_set_change_pending_ = true; | 1274 surface_set_change_pending_ = true; |
| 1276 | 1275 |
| 1277 FinishSurfaceSetChangeIfNeeded(); | 1276 FinishSurfaceSetChangeIfNeeded(); |
| 1278 } | 1277 } |
| 1279 | 1278 |
| 1280 void V4L2SliceVideoDecodeAccelerator::FinishSurfaceSetChangeIfNeeded() { | 1279 void V4L2SliceVideoDecodeAccelerator::FinishSurfaceSetChangeIfNeeded() { |
| 1281 DVLOGF(2); | 1280 DVLOGF(2); |
| 1282 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 1281 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1283 | 1282 |
| 1284 if (!surface_set_change_pending_ || !surfaces_at_device_.empty()) | 1283 if (!surface_set_change_pending_ || !surfaces_at_device_.empty()) |
| 1285 return; | 1284 return; |
| 1286 | 1285 |
| 1287 DCHECK_EQ(state_, kIdle); | 1286 DCHECK_EQ(state_, kIdle); |
| 1288 DCHECK(decoder_display_queue_.empty()); | 1287 DCHECK(decoder_display_queue_.empty()); |
| 1289 // All output buffers should've been returned from decoder and device by now. | 1288 // All output buffers should've been returned from decoder and device by now. |
| 1290 // The only remaining owner of surfaces may be display (client), and we will | 1289 // The only remaining owner of surfaces may be display (client), and we will |
| 1291 // dismiss them when destroying output buffers below. | 1290 // dismiss them when destroying output buffers below. |
| 1292 DCHECK_EQ(free_output_buffers_.size() + surfaces_at_display_.size(), | 1291 DCHECK_EQ(free_output_buffers_.size() + surfaces_at_display_.size(), |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1319 | 1318 |
| 1320 DVLOGF(3) << "Surface set change finished"; | 1319 DVLOGF(3) << "Surface set change finished"; |
| 1321 | 1320 |
| 1322 surface_set_change_pending_ = false; | 1321 surface_set_change_pending_ = false; |
| 1323 state_ = kDecoding; | 1322 state_ = kDecoding; |
| 1324 ScheduleDecodeBufferTaskIfNeeded(); | 1323 ScheduleDecodeBufferTaskIfNeeded(); |
| 1325 } | 1324 } |
| 1326 | 1325 |
| 1327 bool V4L2SliceVideoDecodeAccelerator::DestroyOutputs(bool dismiss) { | 1326 bool V4L2SliceVideoDecodeAccelerator::DestroyOutputs(bool dismiss) { |
| 1328 DVLOGF(3); | 1327 DVLOGF(3); |
| 1329 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 1328 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1330 std::vector<EGLImageKHR> egl_images_to_destroy; | 1329 std::vector<EGLImageKHR> egl_images_to_destroy; |
| 1331 std::vector<int32> picture_buffers_to_dismiss; | 1330 std::vector<int32> picture_buffers_to_dismiss; |
| 1332 | 1331 |
| 1333 if (output_buffer_map_.empty()) | 1332 if (output_buffer_map_.empty()) |
| 1334 return true; | 1333 return true; |
| 1335 | 1334 |
| 1336 for (auto output_record : output_buffer_map_) { | 1335 for (auto output_record : output_buffer_map_) { |
| 1337 DCHECK(!output_record.at_device); | 1336 DCHECK(!output_record.at_device); |
| 1338 | 1337 |
| 1339 if (output_record.egl_sync != EGL_NO_SYNC_KHR) { | 1338 if (output_record.egl_sync != EGL_NO_SYNC_KHR) { |
| 1340 if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) | 1339 if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) |
| 1341 DVLOGF(1) << "eglDestroySyncKHR failed."; | 1340 DVLOGF(1) << "eglDestroySyncKHR failed."; |
| 1342 } | 1341 } |
| 1343 | 1342 |
| 1344 if (output_record.egl_image != EGL_NO_IMAGE_KHR) { | 1343 if (output_record.egl_image != EGL_NO_IMAGE_KHR) { |
| 1345 child_message_loop_proxy_->PostTask( | 1344 child_task_runner_->PostTask( |
| 1346 FROM_HERE, | 1345 FROM_HERE, |
| 1347 base::Bind(base::IgnoreResult(&V4L2Device::DestroyEGLImage), device_, | 1346 base::Bind(base::IgnoreResult(&V4L2Device::DestroyEGLImage), device_, |
| 1348 egl_display_, output_record.egl_image)); | 1347 egl_display_, output_record.egl_image)); |
| 1349 } | 1348 } |
| 1350 | 1349 |
| 1351 picture_buffers_to_dismiss.push_back(output_record.picture_id); | 1350 picture_buffers_to_dismiss.push_back(output_record.picture_id); |
| 1352 } | 1351 } |
| 1353 | 1352 |
| 1354 if (dismiss) { | 1353 if (dismiss) { |
| 1355 DVLOGF(2) << "Scheduling picture dismissal"; | 1354 DVLOGF(2) << "Scheduling picture dismissal"; |
| 1356 base::WaitableEvent done(false, false); | 1355 base::WaitableEvent done(false, false); |
| 1357 child_message_loop_proxy_->PostTask( | 1356 child_task_runner_->PostTask( |
| 1358 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DismissPictures, | 1357 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DismissPictures, |
| 1359 weak_this_, picture_buffers_to_dismiss, &done)); | 1358 weak_this_, picture_buffers_to_dismiss, &done)); |
| 1360 done.Wait(); | 1359 done.Wait(); |
| 1361 } | 1360 } |
| 1362 | 1361 |
| 1363 // At this point client can't call ReusePictureBuffer on any of the pictures | 1362 // At this point client can't call ReusePictureBuffer on any of the pictures |
| 1364 // anymore, so it's safe to destroy. | 1363 // anymore, so it's safe to destroy. |
| 1365 return DestroyOutputBuffers(); | 1364 return DestroyOutputBuffers(); |
| 1366 } | 1365 } |
| 1367 | 1366 |
| 1368 bool V4L2SliceVideoDecodeAccelerator::DestroyOutputBuffers() { | 1367 bool V4L2SliceVideoDecodeAccelerator::DestroyOutputBuffers() { |
| 1369 DVLOGF(3); | 1368 DVLOGF(3); |
| 1370 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread() || | 1369 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread() || |
| 1371 !decoder_thread_.IsRunning()); | 1370 !decoder_thread_.IsRunning()); |
| 1372 DCHECK(!output_streamon_); | 1371 DCHECK(!output_streamon_); |
| 1373 DCHECK(surfaces_at_device_.empty()); | 1372 DCHECK(surfaces_at_device_.empty()); |
| 1374 DCHECK(decoder_display_queue_.empty()); | 1373 DCHECK(decoder_display_queue_.empty()); |
| 1375 DCHECK_EQ(surfaces_at_display_.size() + free_output_buffers_.size(), | 1374 DCHECK_EQ(surfaces_at_display_.size() + free_output_buffers_.size(), |
| 1376 output_buffer_map_.size()); | 1375 output_buffer_map_.size()); |
| 1377 | 1376 |
| 1378 if (output_buffer_map_.empty()) | 1377 if (output_buffer_map_.empty()) |
| 1379 return true; | 1378 return true; |
| 1380 | 1379 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1402 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1401 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1403 reqbufs.memory = V4L2_MEMORY_MMAP; | 1402 reqbufs.memory = V4L2_MEMORY_MMAP; |
| 1404 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); | 1403 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); |
| 1405 | 1404 |
| 1406 return true; | 1405 return true; |
| 1407 } | 1406 } |
| 1408 | 1407 |
| 1409 void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffers( | 1408 void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffers( |
| 1410 const std::vector<media::PictureBuffer>& buffers) { | 1409 const std::vector<media::PictureBuffer>& buffers) { |
| 1411 DVLOGF(3); | 1410 DVLOGF(3); |
| 1412 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 1411 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 1413 | 1412 |
| 1414 if (buffers.size() != output_buffer_map_.size()) { | 1413 if (buffers.size() != output_buffer_map_.size()) { |
| 1415 DLOG(ERROR) << "Failed to provide requested picture buffers. " | 1414 DLOG(ERROR) << "Failed to provide requested picture buffers. " |
| 1416 << "(Got " << buffers.size() | 1415 << "(Got " << buffers.size() |
| 1417 << ", requested " << output_buffer_map_.size() << ")"; | 1416 << ", requested " << output_buffer_map_.size() << ")"; |
| 1418 NOTIFY_ERROR(INVALID_ARGUMENT); | 1417 NOTIFY_ERROR(INVALID_ARGUMENT); |
| 1419 return; | 1418 return; |
| 1420 } | 1419 } |
| 1421 | 1420 |
| 1422 if (!make_context_current_.Run()) { | 1421 if (!make_context_current_.Run()) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1461 output_record.picture_id = buffers[i].id(); | 1460 output_record.picture_id = buffers[i].id(); |
| 1462 free_output_buffers_.push_back(i); | 1461 free_output_buffers_.push_back(i); |
| 1463 DVLOGF(3) << "buffer[" << i << "]: picture_id=" << output_record.picture_id; | 1462 DVLOGF(3) << "buffer[" << i << "]: picture_id=" << output_record.picture_id; |
| 1464 } | 1463 } |
| 1465 | 1464 |
| 1466 pictures_assigned_.Signal(); | 1465 pictures_assigned_.Signal(); |
| 1467 } | 1466 } |
| 1468 | 1467 |
| 1469 void V4L2SliceVideoDecodeAccelerator::ReusePictureBuffer( | 1468 void V4L2SliceVideoDecodeAccelerator::ReusePictureBuffer( |
| 1470 int32 picture_buffer_id) { | 1469 int32 picture_buffer_id) { |
| 1471 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 1470 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 1472 DVLOGF(4) << "picture_buffer_id=" << picture_buffer_id; | 1471 DVLOGF(4) << "picture_buffer_id=" << picture_buffer_id; |
| 1473 | 1472 |
| 1474 if (!make_context_current_.Run()) { | 1473 if (!make_context_current_.Run()) { |
| 1475 LOGF(ERROR) << "could not make context current"; | 1474 LOGF(ERROR) << "could not make context current"; |
| 1476 NOTIFY_ERROR(PLATFORM_FAILURE); | 1475 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1477 return; | 1476 return; |
| 1478 } | 1477 } |
| 1479 | 1478 |
| 1480 EGLSyncKHR egl_sync = | 1479 EGLSyncKHR egl_sync = |
| 1481 eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); | 1480 eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); |
| 1482 if (egl_sync == EGL_NO_SYNC_KHR) { | 1481 if (egl_sync == EGL_NO_SYNC_KHR) { |
| 1483 LOGF(ERROR) << "eglCreateSyncKHR() failed"; | 1482 LOGF(ERROR) << "eglCreateSyncKHR() failed"; |
| 1484 NOTIFY_ERROR(PLATFORM_FAILURE); | 1483 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1485 return; | 1484 return; |
| 1486 } | 1485 } |
| 1487 | 1486 |
| 1488 scoped_ptr<EGLSyncKHRRef> egl_sync_ref( | 1487 scoped_ptr<EGLSyncKHRRef> egl_sync_ref( |
| 1489 new EGLSyncKHRRef(egl_display_, egl_sync)); | 1488 new EGLSyncKHRRef(egl_display_, egl_sync)); |
| 1490 decoder_thread_proxy_->PostTask( | 1489 decoder_thread_task_runner_->PostTask( |
| 1491 FROM_HERE, | 1490 FROM_HERE, |
| 1492 base::Bind(&V4L2SliceVideoDecodeAccelerator::ReusePictureBufferTask, | 1491 base::Bind(&V4L2SliceVideoDecodeAccelerator::ReusePictureBufferTask, |
| 1493 base::Unretained(this), picture_buffer_id, | 1492 base::Unretained(this), picture_buffer_id, |
| 1494 base::Passed(&egl_sync_ref))); | 1493 base::Passed(&egl_sync_ref))); |
| 1495 } | 1494 } |
| 1496 | 1495 |
| 1497 void V4L2SliceVideoDecodeAccelerator::ReusePictureBufferTask( | 1496 void V4L2SliceVideoDecodeAccelerator::ReusePictureBufferTask( |
| 1498 int32 picture_buffer_id, | 1497 int32 picture_buffer_id, |
| 1499 scoped_ptr<EGLSyncKHRRef> egl_sync_ref) { | 1498 scoped_ptr<EGLSyncKHRRef> egl_sync_ref) { |
| 1500 DVLOGF(3) << "picture_buffer_id=" << picture_buffer_id; | 1499 DVLOGF(3) << "picture_buffer_id=" << picture_buffer_id; |
| 1501 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 1500 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1502 | 1501 |
| 1503 V4L2DecodeSurfaceByPictureBufferId::iterator it = | 1502 V4L2DecodeSurfaceByPictureBufferId::iterator it = |
| 1504 surfaces_at_display_.find(picture_buffer_id); | 1503 surfaces_at_display_.find(picture_buffer_id); |
| 1505 if (it == surfaces_at_display_.end()) { | 1504 if (it == surfaces_at_display_.end()) { |
| 1506 // It's possible that we've already posted a DismissPictureBuffer for this | 1505 // It's possible that we've already posted a DismissPictureBuffer for this |
| 1507 // picture, but it has not yet executed when this ReusePictureBuffer was | 1506 // picture, but it has not yet executed when this ReusePictureBuffer was |
| 1508 // posted to us by the client. In that case just ignore this (we've already | 1507 // posted to us by the client. In that case just ignore this (we've already |
| 1509 // dismissed it and accounted for that) and let the sync object get | 1508 // dismissed it and accounted for that) and let the sync object get |
| 1510 // destroyed. | 1509 // destroyed. |
| 1511 DVLOGF(3) << "got picture id=" << picture_buffer_id | 1510 DVLOGF(3) << "got picture id=" << picture_buffer_id |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1524 DCHECK(!output_record.at_device); | 1523 DCHECK(!output_record.at_device); |
| 1525 output_record.at_client = false; | 1524 output_record.at_client = false; |
| 1526 output_record.egl_sync = egl_sync_ref->egl_sync; | 1525 output_record.egl_sync = egl_sync_ref->egl_sync; |
| 1527 // Take ownership of the EGLSync. | 1526 // Take ownership of the EGLSync. |
| 1528 egl_sync_ref->egl_sync = EGL_NO_SYNC_KHR; | 1527 egl_sync_ref->egl_sync = EGL_NO_SYNC_KHR; |
| 1529 surfaces_at_display_.erase(it); | 1528 surfaces_at_display_.erase(it); |
| 1530 } | 1529 } |
| 1531 | 1530 |
| 1532 void V4L2SliceVideoDecodeAccelerator::Flush() { | 1531 void V4L2SliceVideoDecodeAccelerator::Flush() { |
| 1533 DVLOGF(3); | 1532 DVLOGF(3); |
| 1534 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 1533 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 1535 | 1534 |
| 1536 decoder_thread_proxy_->PostTask( | 1535 decoder_thread_task_runner_->PostTask( |
| 1537 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::FlushTask, | 1536 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::FlushTask, |
| 1538 base::Unretained(this))); | 1537 base::Unretained(this))); |
| 1539 } | 1538 } |
| 1540 | 1539 |
| 1541 void V4L2SliceVideoDecodeAccelerator::FlushTask() { | 1540 void V4L2SliceVideoDecodeAccelerator::FlushTask() { |
| 1542 DVLOGF(3); | 1541 DVLOGF(3); |
| 1543 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 1542 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1544 | 1543 |
| 1545 if (!decoder_input_queue_.empty()) { | 1544 if (!decoder_input_queue_.empty()) { |
| 1546 // We are not done with pending inputs, so queue an empty buffer, | 1545 // We are not done with pending inputs, so queue an empty buffer, |
| 1547 // which - when reached - will trigger flush sequence. | 1546 // which - when reached - will trigger flush sequence. |
| 1548 decoder_input_queue_.push( | 1547 decoder_input_queue_.push( |
| 1549 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( | 1548 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( |
| 1550 io_client_, io_message_loop_proxy_, nullptr, 0, kFlushBufferId))); | 1549 io_client_, io_task_runner_, nullptr, 0, kFlushBufferId))); |
| 1551 return; | 1550 return; |
| 1552 } | 1551 } |
| 1553 | 1552 |
| 1554 // No more inputs pending, so just finish flushing here. | 1553 // No more inputs pending, so just finish flushing here. |
| 1555 InitiateFlush(); | 1554 InitiateFlush(); |
| 1556 } | 1555 } |
| 1557 | 1556 |
| 1558 void V4L2SliceVideoDecodeAccelerator::InitiateFlush() { | 1557 void V4L2SliceVideoDecodeAccelerator::InitiateFlush() { |
| 1559 DVLOGF(3); | 1558 DVLOGF(3); |
| 1560 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 1559 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1561 | 1560 |
| 1562 DCHECK(!decoder_flushing_); | 1561 DCHECK(!decoder_flushing_); |
| 1563 DCHECK_EQ(state_, kDecoding); | 1562 DCHECK_EQ(state_, kDecoding); |
| 1564 state_ = kIdle; | 1563 state_ = kIdle; |
| 1565 | 1564 |
| 1566 // This will trigger output for all remaining surfaces in the decoder. | 1565 // This will trigger output for all remaining surfaces in the decoder. |
| 1567 // However, not all of them may be decoded yet (they would be queued | 1566 // However, not all of them may be decoded yet (they would be queued |
| 1568 // in hardware then). | 1567 // in hardware then). |
| 1569 if (!decoder_->Flush()) { | 1568 if (!decoder_->Flush()) { |
| 1570 DVLOGF(1) << "Failed flushing the decoder."; | 1569 DVLOGF(1) << "Failed flushing the decoder."; |
| 1571 NOTIFY_ERROR(PLATFORM_FAILURE); | 1570 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1572 return; | 1571 return; |
| 1573 } | 1572 } |
| 1574 | 1573 |
| 1575 // Put the decoder in an idle state, ready to resume. | 1574 // Put the decoder in an idle state, ready to resume. |
| 1576 decoder_->Reset(); | 1575 decoder_->Reset(); |
| 1577 | 1576 |
| 1578 decoder_flushing_ = true; | 1577 decoder_flushing_ = true; |
| 1579 | 1578 |
| 1580 decoder_thread_proxy_->PostTask( | 1579 decoder_thread_task_runner_->PostTask( |
| 1581 FROM_HERE, | 1580 FROM_HERE, |
| 1582 base::Bind(&V4L2SliceVideoDecodeAccelerator::FinishFlushIfNeeded, | 1581 base::Bind(&V4L2SliceVideoDecodeAccelerator::FinishFlushIfNeeded, |
| 1583 base::Unretained(this))); | 1582 base::Unretained(this))); |
| 1584 } | 1583 } |
| 1585 | 1584 |
| 1586 void V4L2SliceVideoDecodeAccelerator::FinishFlushIfNeeded() { | 1585 void V4L2SliceVideoDecodeAccelerator::FinishFlushIfNeeded() { |
| 1587 DVLOGF(3); | 1586 DVLOGF(3); |
| 1588 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 1587 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1589 | 1588 |
| 1590 if (!decoder_flushing_ || !surfaces_at_device_.empty()) | 1589 if (!decoder_flushing_ || !surfaces_at_device_.empty()) |
| 1591 return; | 1590 return; |
| 1592 | 1591 |
| 1593 DCHECK_EQ(state_, kIdle); | 1592 DCHECK_EQ(state_, kIdle); |
| 1594 | 1593 |
| 1595 // At this point, all remaining surfaces are decoded and dequeued, and since | 1594 // At this point, all remaining surfaces are decoded and dequeued, and since |
| 1596 // we have already scheduled output for them in InitiateFlush(), their | 1595 // we have already scheduled output for them in InitiateFlush(), their |
| 1597 // respective PictureReady calls have been posted (or they have been queued on | 1596 // respective PictureReady calls have been posted (or they have been queued on |
| 1598 // pending_picture_ready_). So at this time, once we SendPictureReady(), | 1597 // pending_picture_ready_). So at this time, once we SendPictureReady(), |
| 1599 // we will have all remaining PictureReady() posted to the client and we | 1598 // we will have all remaining PictureReady() posted to the client and we |
| 1600 // can post NotifyFlushDone(). | 1599 // can post NotifyFlushDone(). |
| 1601 DCHECK(decoder_display_queue_.empty()); | 1600 DCHECK(decoder_display_queue_.empty()); |
| 1602 | 1601 |
| 1603 // Decoder should have already returned all surfaces and all surfaces are | 1602 // Decoder should have already returned all surfaces and all surfaces are |
| 1604 // out of hardware. There can be no other owners of input buffers. | 1603 // out of hardware. There can be no other owners of input buffers. |
| 1605 DCHECK_EQ(free_input_buffers_.size(), input_buffer_map_.size()); | 1604 DCHECK_EQ(free_input_buffers_.size(), input_buffer_map_.size()); |
| 1606 | 1605 |
| 1607 SendPictureReady(); | 1606 SendPictureReady(); |
| 1608 | 1607 |
| 1609 child_message_loop_proxy_->PostTask( | 1608 child_task_runner_->PostTask(FROM_HERE, |
| 1610 FROM_HERE, base::Bind(&Client::NotifyFlushDone, client_)); | 1609 base::Bind(&Client::NotifyFlushDone, client_)); |
| 1611 | 1610 |
| 1612 decoder_flushing_ = false; | 1611 decoder_flushing_ = false; |
| 1613 | 1612 |
| 1614 DVLOGF(3) << "Flush finished"; | 1613 DVLOGF(3) << "Flush finished"; |
| 1615 state_ = kDecoding; | 1614 state_ = kDecoding; |
| 1616 ScheduleDecodeBufferTaskIfNeeded(); | 1615 ScheduleDecodeBufferTaskIfNeeded(); |
| 1617 } | 1616 } |
| 1618 | 1617 |
| 1619 void V4L2SliceVideoDecodeAccelerator::Reset() { | 1618 void V4L2SliceVideoDecodeAccelerator::Reset() { |
| 1620 DVLOGF(3); | 1619 DVLOGF(3); |
| 1621 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 1620 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 1622 | 1621 |
| 1623 decoder_thread_proxy_->PostTask( | 1622 decoder_thread_task_runner_->PostTask( |
| 1624 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::ResetTask, | 1623 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::ResetTask, |
| 1625 base::Unretained(this))); | 1624 base::Unretained(this))); |
| 1626 } | 1625 } |
| 1627 | 1626 |
| 1628 void V4L2SliceVideoDecodeAccelerator::ResetTask() { | 1627 void V4L2SliceVideoDecodeAccelerator::ResetTask() { |
| 1629 DVLOGF(3); | 1628 DVLOGF(3); |
| 1630 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 1629 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1631 | 1630 |
| 1632 if (decoder_resetting_) { | 1631 if (decoder_resetting_) { |
| 1633 // This is a bug in the client, multiple Reset()s before NotifyResetDone() | 1632 // This is a bug in the client, multiple Reset()s before NotifyResetDone() |
| 1634 // are not allowed. | 1633 // are not allowed. |
| 1635 NOTREACHED() << "Client should not be requesting multiple Reset()s"; | 1634 NOTREACHED() << "Client should not be requesting multiple Reset()s"; |
| 1636 return; | 1635 return; |
| 1637 } | 1636 } |
| 1638 | 1637 |
| 1639 DCHECK_EQ(state_, kDecoding); | 1638 DCHECK_EQ(state_, kDecoding); |
| 1640 state_ = kIdle; | 1639 state_ = kIdle; |
| 1641 | 1640 |
| 1642 // Put the decoder in an idle state, ready to resume. | 1641 // Put the decoder in an idle state, ready to resume. |
| 1643 decoder_->Reset(); | 1642 decoder_->Reset(); |
| 1644 | 1643 |
| 1645 decoder_resetting_ = true; | 1644 decoder_resetting_ = true; |
| 1646 | 1645 |
| 1647 // Drop all remaining inputs. | 1646 // Drop all remaining inputs. |
| 1648 decoder_current_bitstream_buffer_.reset(); | 1647 decoder_current_bitstream_buffer_.reset(); |
| 1649 while (!decoder_input_queue_.empty()) | 1648 while (!decoder_input_queue_.empty()) |
| 1650 decoder_input_queue_.pop(); | 1649 decoder_input_queue_.pop(); |
| 1651 | 1650 |
| 1652 FinishResetIfNeeded(); | 1651 FinishResetIfNeeded(); |
| 1653 } | 1652 } |
| 1654 | 1653 |
| 1655 void V4L2SliceVideoDecodeAccelerator::FinishResetIfNeeded() { | 1654 void V4L2SliceVideoDecodeAccelerator::FinishResetIfNeeded() { |
| 1656 DVLOGF(3); | 1655 DVLOGF(3); |
| 1657 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 1656 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1658 | 1657 |
| 1659 if (!decoder_resetting_ || !surfaces_at_device_.empty()) | 1658 if (!decoder_resetting_ || !surfaces_at_device_.empty()) |
| 1660 return; | 1659 return; |
| 1661 | 1660 |
| 1662 DCHECK_EQ(state_, kIdle); | 1661 DCHECK_EQ(state_, kIdle); |
| 1663 DCHECK(!decoder_flushing_); | 1662 DCHECK(!decoder_flushing_); |
| 1664 SendPictureReady(); | 1663 SendPictureReady(); |
| 1665 | 1664 |
| 1666 // Drop any pending outputs. | 1665 // Drop any pending outputs. |
| 1667 while (!decoder_display_queue_.empty()) | 1666 while (!decoder_display_queue_.empty()) |
| 1668 decoder_display_queue_.pop(); | 1667 decoder_display_queue_.pop(); |
| 1669 | 1668 |
| 1670 // At this point we can have no input buffers in the decoder, because we | 1669 // At this point we can have no input buffers in the decoder, because we |
| 1671 // Reset()ed it in ResetTask(), and have not scheduled any new Decode()s | 1670 // Reset()ed it in ResetTask(), and have not scheduled any new Decode()s |
| 1672 // having been in kIdle since. We don't have any surfaces in the HW either - | 1671 // having been in kIdle since. We don't have any surfaces in the HW either - |
| 1673 // we just checked that surfaces_at_device_.empty(), and inputs are tied | 1672 // we just checked that surfaces_at_device_.empty(), and inputs are tied |
| 1674 // to surfaces. Since there can be no other owners of input buffers, we can | 1673 // to surfaces. Since there can be no other owners of input buffers, we can |
| 1675 // simply mark them all as available. | 1674 // simply mark them all as available. |
| 1676 DCHECK_EQ(input_buffer_queued_count_, 0); | 1675 DCHECK_EQ(input_buffer_queued_count_, 0); |
| 1677 free_input_buffers_.clear(); | 1676 free_input_buffers_.clear(); |
| 1678 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { | 1677 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { |
| 1679 DCHECK(!input_buffer_map_[i].at_device); | 1678 DCHECK(!input_buffer_map_[i].at_device); |
| 1680 ReuseInputBuffer(i); | 1679 ReuseInputBuffer(i); |
| 1681 } | 1680 } |
| 1682 | 1681 |
| 1683 decoder_resetting_ = false; | 1682 decoder_resetting_ = false; |
| 1684 | 1683 |
| 1685 child_message_loop_proxy_->PostTask( | 1684 child_task_runner_->PostTask(FROM_HERE, |
| 1686 FROM_HERE, base::Bind(&Client::NotifyResetDone, client_)); | 1685 base::Bind(&Client::NotifyResetDone, client_)); |
| 1687 | 1686 |
| 1688 DVLOGF(3) << "Reset finished"; | 1687 DVLOGF(3) << "Reset finished"; |
| 1689 | 1688 |
| 1690 state_ = kDecoding; | 1689 state_ = kDecoding; |
| 1691 ScheduleDecodeBufferTaskIfNeeded(); | 1690 ScheduleDecodeBufferTaskIfNeeded(); |
| 1692 } | 1691 } |
| 1693 | 1692 |
| 1694 void V4L2SliceVideoDecodeAccelerator::SetErrorState(Error error) { | 1693 void V4L2SliceVideoDecodeAccelerator::SetErrorState(Error error) { |
| 1695 // We can touch decoder_state_ only if this is the decoder thread or the | 1694 // We can touch decoder_state_ only if this is the decoder thread or the |
| 1696 // decoder thread isn't running. | 1695 // decoder thread isn't running. |
| 1697 if (decoder_thread_.IsRunning() && | 1696 if (decoder_thread_.IsRunning() && |
| 1698 !decoder_thread_proxy_->BelongsToCurrentThread()) { | 1697 !decoder_thread_task_runner_->BelongsToCurrentThread()) { |
| 1699 decoder_thread_proxy_->PostTask( | 1698 decoder_thread_task_runner_->PostTask( |
| 1700 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::SetErrorState, | 1699 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::SetErrorState, |
| 1701 base::Unretained(this), error)); | 1700 base::Unretained(this), error)); |
| 1702 return; | 1701 return; |
| 1703 } | 1702 } |
| 1704 | 1703 |
| 1705 // Post NotifyError only if we are already initialized, as the API does | 1704 // Post NotifyError only if we are already initialized, as the API does |
| 1706 // not allow doing so before that. | 1705 // not allow doing so before that. |
| 1707 if (state_ != kError && state_ != kUninitialized) | 1706 if (state_ != kError && state_ != kUninitialized) |
| 1708 NotifyError(error); | 1707 NotifyError(error); |
| 1709 | 1708 |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2042 memset(data_copy.get(), 0, data_copy_size); | 2041 memset(data_copy.get(), 0, data_copy_size); |
| 2043 data_copy[2] = 0x01; | 2042 data_copy[2] = 0x01; |
| 2044 memcpy(data_copy.get() + 3, data, size); | 2043 memcpy(data_copy.get() + 3, data, size); |
| 2045 return v4l2_dec_->SubmitSlice(dec_surface->input_record(), data_copy.get(), | 2044 return v4l2_dec_->SubmitSlice(dec_surface->input_record(), data_copy.get(), |
| 2046 data_copy_size); | 2045 data_copy_size); |
| 2047 } | 2046 } |
| 2048 | 2047 |
| 2049 bool V4L2SliceVideoDecodeAccelerator::SubmitSlice(int index, | 2048 bool V4L2SliceVideoDecodeAccelerator::SubmitSlice(int index, |
| 2050 const uint8_t* data, | 2049 const uint8_t* data, |
| 2051 size_t size) { | 2050 size_t size) { |
| 2052 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 2051 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 2053 | 2052 |
| 2054 InputRecord& input_record = input_buffer_map_[index]; | 2053 InputRecord& input_record = input_buffer_map_[index]; |
| 2055 | 2054 |
| 2056 if (input_record.bytes_used + size > input_record.length) { | 2055 if (input_record.bytes_used + size > input_record.length) { |
| 2057 DVLOGF(1) << "Input buffer too small"; | 2056 DVLOGF(1) << "Input buffer too small"; |
| 2058 return false; | 2057 return false; |
| 2059 } | 2058 } |
| 2060 | 2059 |
| 2061 memcpy(static_cast<uint8_t*>(input_record.address) + input_record.bytes_used, | 2060 memcpy(static_cast<uint8_t*>(input_record.address) + input_record.bytes_used, |
| 2062 data, size); | 2061 data, size); |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2354 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> | 2353 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> |
| 2355 V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator:: | 2354 V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator:: |
| 2356 VP8PictureToV4L2DecodeSurface(const scoped_refptr<VP8Picture>& pic) { | 2355 VP8PictureToV4L2DecodeSurface(const scoped_refptr<VP8Picture>& pic) { |
| 2357 V4L2VP8Picture* v4l2_pic = pic->AsV4L2VP8Picture(); | 2356 V4L2VP8Picture* v4l2_pic = pic->AsV4L2VP8Picture(); |
| 2358 CHECK(v4l2_pic); | 2357 CHECK(v4l2_pic); |
| 2359 return v4l2_pic->dec_surface(); | 2358 return v4l2_pic->dec_surface(); |
| 2360 } | 2359 } |
| 2361 | 2360 |
| 2362 void V4L2SliceVideoDecodeAccelerator::DecodeSurface( | 2361 void V4L2SliceVideoDecodeAccelerator::DecodeSurface( |
| 2363 const scoped_refptr<V4L2DecodeSurface>& dec_surface) { | 2362 const scoped_refptr<V4L2DecodeSurface>& dec_surface) { |
| 2364 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 2363 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 2365 | 2364 |
| 2366 DVLOGF(3) << "Submitting decode for surface: " << dec_surface->ToString(); | 2365 DVLOGF(3) << "Submitting decode for surface: " << dec_surface->ToString(); |
| 2367 Enqueue(dec_surface); | 2366 Enqueue(dec_surface); |
| 2368 } | 2367 } |
| 2369 | 2368 |
| 2370 void V4L2SliceVideoDecodeAccelerator::SurfaceReady( | 2369 void V4L2SliceVideoDecodeAccelerator::SurfaceReady( |
| 2371 const scoped_refptr<V4L2DecodeSurface>& dec_surface) { | 2370 const scoped_refptr<V4L2DecodeSurface>& dec_surface) { |
| 2372 DVLOGF(3); | 2371 DVLOGF(3); |
| 2373 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 2372 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 2374 | 2373 |
| 2375 decoder_display_queue_.push(dec_surface); | 2374 decoder_display_queue_.push(dec_surface); |
| 2376 TryOutputSurfaces(); | 2375 TryOutputSurfaces(); |
| 2377 } | 2376 } |
| 2378 | 2377 |
| 2379 void V4L2SliceVideoDecodeAccelerator::TryOutputSurfaces() { | 2378 void V4L2SliceVideoDecodeAccelerator::TryOutputSurfaces() { |
| 2380 while (!decoder_display_queue_.empty()) { | 2379 while (!decoder_display_queue_.empty()) { |
| 2381 scoped_refptr<V4L2DecodeSurface> dec_surface = | 2380 scoped_refptr<V4L2DecodeSurface> dec_surface = |
| 2382 decoder_display_queue_.front(); | 2381 decoder_display_queue_.front(); |
| 2383 | 2382 |
| 2384 if (!dec_surface->decoded()) | 2383 if (!dec_surface->decoded()) |
| 2385 break; | 2384 break; |
| 2386 | 2385 |
| 2387 decoder_display_queue_.pop(); | 2386 decoder_display_queue_.pop(); |
| 2388 OutputSurface(dec_surface); | 2387 OutputSurface(dec_surface); |
| 2389 } | 2388 } |
| 2390 } | 2389 } |
| 2391 | 2390 |
| 2392 void V4L2SliceVideoDecodeAccelerator::OutputSurface( | 2391 void V4L2SliceVideoDecodeAccelerator::OutputSurface( |
| 2393 const scoped_refptr<V4L2DecodeSurface>& dec_surface) { | 2392 const scoped_refptr<V4L2DecodeSurface>& dec_surface) { |
| 2394 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 2393 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 2395 | 2394 |
| 2396 OutputRecord& output_record = | 2395 OutputRecord& output_record = |
| 2397 output_buffer_map_[dec_surface->output_record()]; | 2396 output_buffer_map_[dec_surface->output_record()]; |
| 2398 | 2397 |
| 2399 bool inserted = | 2398 bool inserted = |
| 2400 surfaces_at_display_.insert(std::make_pair(output_record.picture_id, | 2399 surfaces_at_display_.insert(std::make_pair(output_record.picture_id, |
| 2401 dec_surface)).second; | 2400 dec_surface)).second; |
| 2402 DCHECK(inserted); | 2401 DCHECK(inserted); |
| 2403 | 2402 |
| 2404 DCHECK(!output_record.at_client); | 2403 DCHECK(!output_record.at_client); |
| 2405 DCHECK(!output_record.at_device); | 2404 DCHECK(!output_record.at_device); |
| 2406 DCHECK_NE(output_record.egl_image, EGL_NO_IMAGE_KHR); | 2405 DCHECK_NE(output_record.egl_image, EGL_NO_IMAGE_KHR); |
| 2407 DCHECK_NE(output_record.picture_id, -1); | 2406 DCHECK_NE(output_record.picture_id, -1); |
| 2408 output_record.at_client = true; | 2407 output_record.at_client = true; |
| 2409 | 2408 |
| 2410 media::Picture picture(output_record.picture_id, dec_surface->bitstream_id(), | 2409 media::Picture picture(output_record.picture_id, dec_surface->bitstream_id(), |
| 2411 gfx::Rect(visible_size_), false); | 2410 gfx::Rect(visible_size_), false); |
| 2412 DVLOGF(3) << dec_surface->ToString() | 2411 DVLOGF(3) << dec_surface->ToString() |
| 2413 << ", bitstream_id: " << picture.bitstream_buffer_id() | 2412 << ", bitstream_id: " << picture.bitstream_buffer_id() |
| 2414 << ", picture_id: " << picture.picture_buffer_id(); | 2413 << ", picture_id: " << picture.picture_buffer_id(); |
| 2415 pending_picture_ready_.push(PictureRecord(output_record.cleared, picture)); | 2414 pending_picture_ready_.push(PictureRecord(output_record.cleared, picture)); |
| 2416 SendPictureReady(); | 2415 SendPictureReady(); |
| 2417 output_record.cleared = true; | 2416 output_record.cleared = true; |
| 2418 } | 2417 } |
| 2419 | 2418 |
| 2420 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> | 2419 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> |
| 2421 V4L2SliceVideoDecodeAccelerator::CreateSurface() { | 2420 V4L2SliceVideoDecodeAccelerator::CreateSurface() { |
| 2422 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 2421 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 2423 DCHECK_EQ(state_, kDecoding); | 2422 DCHECK_EQ(state_, kDecoding); |
| 2424 | 2423 |
| 2425 if (free_input_buffers_.empty() || free_output_buffers_.empty()) | 2424 if (free_input_buffers_.empty() || free_output_buffers_.empty()) |
| 2426 return nullptr; | 2425 return nullptr; |
| 2427 | 2426 |
| 2428 int input = free_input_buffers_.front(); | 2427 int input = free_input_buffers_.front(); |
| 2429 free_input_buffers_.pop_front(); | 2428 free_input_buffers_.pop_front(); |
| 2430 int output = free_output_buffers_.front(); | 2429 int output = free_output_buffers_.front(); |
| 2431 free_output_buffers_.pop_front(); | 2430 free_output_buffers_.pop_front(); |
| 2432 | 2431 |
| 2433 InputRecord& input_record = input_buffer_map_[input]; | 2432 InputRecord& input_record = input_buffer_map_[input]; |
| 2434 DCHECK_EQ(input_record.bytes_used, 0u); | 2433 DCHECK_EQ(input_record.bytes_used, 0u); |
| 2435 DCHECK_EQ(input_record.input_id, -1); | 2434 DCHECK_EQ(input_record.input_id, -1); |
| 2436 DCHECK(decoder_current_bitstream_buffer_ != nullptr); | 2435 DCHECK(decoder_current_bitstream_buffer_ != nullptr); |
| 2437 input_record.input_id = decoder_current_bitstream_buffer_->input_id; | 2436 input_record.input_id = decoder_current_bitstream_buffer_->input_id; |
| 2438 | 2437 |
| 2439 scoped_refptr<V4L2DecodeSurface> dec_surface = new V4L2DecodeSurface( | 2438 scoped_refptr<V4L2DecodeSurface> dec_surface = new V4L2DecodeSurface( |
| 2440 decoder_current_bitstream_buffer_->input_id, input, output, | 2439 decoder_current_bitstream_buffer_->input_id, input, output, |
| 2441 base::Bind(&V4L2SliceVideoDecodeAccelerator::ReuseOutputBuffer, | 2440 base::Bind(&V4L2SliceVideoDecodeAccelerator::ReuseOutputBuffer, |
| 2442 base::Unretained(this))); | 2441 base::Unretained(this))); |
| 2443 | 2442 |
| 2444 DVLOGF(4) << "Created surface " << input << " -> " << output; | 2443 DVLOGF(4) << "Created surface " << input << " -> " << output; |
| 2445 return dec_surface; | 2444 return dec_surface; |
| 2446 } | 2445 } |
| 2447 | 2446 |
| 2448 void V4L2SliceVideoDecodeAccelerator::SendPictureReady() { | 2447 void V4L2SliceVideoDecodeAccelerator::SendPictureReady() { |
| 2449 DVLOGF(3); | 2448 DVLOGF(3); |
| 2450 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 2449 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 2451 bool resetting_or_flushing = (decoder_resetting_ || decoder_flushing_); | 2450 bool resetting_or_flushing = (decoder_resetting_ || decoder_flushing_); |
| 2452 while (!pending_picture_ready_.empty()) { | 2451 while (!pending_picture_ready_.empty()) { |
| 2453 bool cleared = pending_picture_ready_.front().cleared; | 2452 bool cleared = pending_picture_ready_.front().cleared; |
| 2454 const media::Picture& picture = pending_picture_ready_.front().picture; | 2453 const media::Picture& picture = pending_picture_ready_.front().picture; |
| 2455 if (cleared && picture_clearing_count_ == 0) { | 2454 if (cleared && picture_clearing_count_ == 0) { |
| 2456 DVLOGF(4) << "Posting picture ready to IO for: " | 2455 DVLOGF(4) << "Posting picture ready to IO for: " |
| 2457 << picture.picture_buffer_id(); | 2456 << picture.picture_buffer_id(); |
| 2458 // This picture is cleared. Post it to IO thread to reduce latency. This | 2457 // This picture is cleared. Post it to IO thread to reduce latency. This |
| 2459 // should be the case after all pictures are cleared at the beginning. | 2458 // should be the case after all pictures are cleared at the beginning. |
| 2460 io_message_loop_proxy_->PostTask( | 2459 io_task_runner_->PostTask( |
| 2461 FROM_HERE, base::Bind(&Client::PictureReady, io_client_, picture)); | 2460 FROM_HERE, base::Bind(&Client::PictureReady, io_client_, picture)); |
| 2462 pending_picture_ready_.pop(); | 2461 pending_picture_ready_.pop(); |
| 2463 } else if (!cleared || resetting_or_flushing) { | 2462 } else if (!cleared || resetting_or_flushing) { |
| 2464 DVLOGF(3) << "cleared=" << pending_picture_ready_.front().cleared | 2463 DVLOGF(3) << "cleared=" << pending_picture_ready_.front().cleared |
| 2465 << ", decoder_resetting_=" << decoder_resetting_ | 2464 << ", decoder_resetting_=" << decoder_resetting_ |
| 2466 << ", decoder_flushing_=" << decoder_flushing_ | 2465 << ", decoder_flushing_=" << decoder_flushing_ |
| 2467 << ", picture_clearing_count_=" << picture_clearing_count_; | 2466 << ", picture_clearing_count_=" << picture_clearing_count_; |
| 2468 DVLOGF(4) << "Posting picture ready to GPU for: " | 2467 DVLOGF(4) << "Posting picture ready to GPU for: " |
| 2469 << picture.picture_buffer_id(); | 2468 << picture.picture_buffer_id(); |
| 2470 // If the picture is not cleared, post it to the child thread because it | 2469 // If the picture is not cleared, post it to the child thread because it |
| 2471 // has to be cleared in the child thread. A picture only needs to be | 2470 // has to be cleared in the child thread. A picture only needs to be |
| 2472 // cleared once. If the decoder is resetting or flushing, send all | 2471 // cleared once. If the decoder is resetting or flushing, send all |
| 2473 // pictures to ensure PictureReady arrive before reset or flush done. | 2472 // pictures to ensure PictureReady arrive before reset or flush done. |
| 2474 child_message_loop_proxy_->PostTaskAndReply( | 2473 child_task_runner_->PostTaskAndReply( |
| 2475 FROM_HERE, base::Bind(&Client::PictureReady, client_, picture), | 2474 FROM_HERE, base::Bind(&Client::PictureReady, client_, picture), |
| 2476 // Unretained is safe. If Client::PictureReady gets to run, |this| is | 2475 // Unretained is safe. If Client::PictureReady gets to run, |this| is |
| 2477 // alive. Destroy() will wait the decode thread to finish. | 2476 // alive. Destroy() will wait the decode thread to finish. |
| 2478 base::Bind(&V4L2SliceVideoDecodeAccelerator::PictureCleared, | 2477 base::Bind(&V4L2SliceVideoDecodeAccelerator::PictureCleared, |
| 2479 base::Unretained(this))); | 2478 base::Unretained(this))); |
| 2480 picture_clearing_count_++; | 2479 picture_clearing_count_++; |
| 2481 pending_picture_ready_.pop(); | 2480 pending_picture_ready_.pop(); |
| 2482 } else { | 2481 } else { |
| 2483 // This picture is cleared. But some pictures are about to be cleared on | 2482 // This picture is cleared. But some pictures are about to be cleared on |
| 2484 // the child thread. To preserve the order, do not send this until those | 2483 // the child thread. To preserve the order, do not send this until those |
| 2485 // pictures are cleared. | 2484 // pictures are cleared. |
| 2486 break; | 2485 break; |
| 2487 } | 2486 } |
| 2488 } | 2487 } |
| 2489 } | 2488 } |
| 2490 | 2489 |
| 2491 void V4L2SliceVideoDecodeAccelerator::PictureCleared() { | 2490 void V4L2SliceVideoDecodeAccelerator::PictureCleared() { |
| 2492 DVLOGF(3) << "clearing count=" << picture_clearing_count_; | 2491 DVLOGF(3) << "clearing count=" << picture_clearing_count_; |
| 2493 DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); | 2492 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 2494 DCHECK_GT(picture_clearing_count_, 0); | 2493 DCHECK_GT(picture_clearing_count_, 0); |
| 2495 picture_clearing_count_--; | 2494 picture_clearing_count_--; |
| 2496 SendPictureReady(); | 2495 SendPictureReady(); |
| 2497 } | 2496 } |
| 2498 | 2497 |
| 2499 bool V4L2SliceVideoDecodeAccelerator::CanDecodeOnIOThread() { | 2498 bool V4L2SliceVideoDecodeAccelerator::CanDecodeOnIOThread() { |
| 2500 return true; | 2499 return true; |
| 2501 } | 2500 } |
| 2502 | 2501 |
| 2503 // static | 2502 // static |
| 2504 media::VideoDecodeAccelerator::SupportedProfiles | 2503 media::VideoDecodeAccelerator::SupportedProfiles |
| 2505 V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles() { | 2504 V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles() { |
| 2506 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); | 2505 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); |
| 2507 if (!device) | 2506 if (!device) |
| 2508 return SupportedProfiles(); | 2507 return SupportedProfiles(); |
| 2509 | 2508 |
| 2510 const uint32_t supported_formats[] = { | 2509 const uint32_t supported_formats[] = { |
| 2511 V4L2_PIX_FMT_H264_SLICE, V4L2_PIX_FMT_VP8_FRAME}; | 2510 V4L2_PIX_FMT_H264_SLICE, V4L2_PIX_FMT_VP8_FRAME}; |
| 2512 return device->GetSupportedDecodeProfiles(arraysize(supported_formats), | 2511 return device->GetSupportedDecodeProfiles(arraysize(supported_formats), |
| 2513 supported_formats); | 2512 supported_formats); |
| 2514 } | 2513 } |
| 2515 | 2514 |
| 2516 } // namespace content | 2515 } // namespace content |
| OLD | NEW |