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

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

Issue 1822983002: Support external buffer import in VDA interface and add a V4L2SVDA impl. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <errno.h> 5 #include <errno.h>
6 #include <fcntl.h> 6 #include <fcntl.h>
7 #include <linux/videodev2.h> 7 #include <linux/videodev2.h>
8 #include <poll.h> 8 #include <poll.h>
9 #include <string.h> 9 #include <string.h>
10 #include <sys/eventfd.h> 10 #include <sys/eventfd.h>
11 #include <sys/ioctl.h> 11 #include <sys/ioctl.h>
12 #include <sys/mman.h> 12 #include <sys/mman.h>
13 13
14 #include "base/bind.h" 14 #include "base/bind.h"
15 #include "base/bind_helpers.h" 15 #include "base/bind_helpers.h"
16 #include "base/callback.h" 16 #include "base/callback.h"
17 #include "base/callback_helpers.h" 17 #include "base/callback_helpers.h"
18 #include "base/command_line.h" 18 #include "base/command_line.h"
19 #include "base/macros.h" 19 #include "base/macros.h"
20 #include "base/memory/ptr_util.h"
20 #include "base/numerics/safe_conversions.h" 21 #include "base/numerics/safe_conversions.h"
21 #include "base/strings/stringprintf.h" 22 #include "base/strings/stringprintf.h"
22 #include "content/common/gpu/media/shared_memory_region.h" 23 #include "content/common/gpu/media/shared_memory_region.h"
23 #include "content/common/gpu/media/v4l2_slice_video_decode_accelerator.h" 24 #include "content/common/gpu/media/v4l2_slice_video_decode_accelerator.h"
24 #include "media/base/bind_to_current_loop.h" 25 #include "media/base/bind_to_current_loop.h"
25 #include "media/base/media_switches.h" 26 #include "media/base/media_switches.h"
26 #include "ui/gl/gl_context.h" 27 #include "ui/gl/gl_context.h"
27 #include "ui/gl/scoped_binders.h" 28 #include "ui/gl/scoped_binders.h"
28 29
29 #define LOGF(level) LOG(level) << __FUNCTION__ << "(): " 30 #define LOGF(level) LOG(level) << __FUNCTION__ << "(): "
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 address(nullptr), 156 address(nullptr),
156 length(0), 157 length(0),
157 bytes_used(0), 158 bytes_used(0),
158 at_device(false) { 159 at_device(false) {
159 } 160 }
160 161
161 V4L2SliceVideoDecodeAccelerator::OutputRecord::OutputRecord() 162 V4L2SliceVideoDecodeAccelerator::OutputRecord::OutputRecord()
162 : at_device(false), 163 : at_device(false),
163 at_client(false), 164 at_client(false),
164 picture_id(-1), 165 picture_id(-1),
166 texture_id(0),
165 egl_image(EGL_NO_IMAGE_KHR), 167 egl_image(EGL_NO_IMAGE_KHR),
166 egl_sync(EGL_NO_SYNC_KHR), 168 egl_sync(EGL_NO_SYNC_KHR),
167 cleared(false) { 169 cleared(false) {}
168 }
169 170
170 struct V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef { 171 struct V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef {
171 BitstreamBufferRef( 172 BitstreamBufferRef(
172 base::WeakPtr<VideoDecodeAccelerator::Client>& client, 173 base::WeakPtr<VideoDecodeAccelerator::Client>& client,
173 const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, 174 const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner,
174 SharedMemoryRegion* shm, 175 SharedMemoryRegion* shm,
175 int32_t input_id); 176 int32_t input_id);
176 ~BitstreamBufferRef(); 177 ~BitstreamBufferRef();
177 const base::WeakPtr<VideoDecodeAccelerator::Client> client; 178 const base::WeakPtr<VideoDecodeAccelerator::Client> client;
178 const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner; 179 const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner;
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 device_(device), 389 device_(device),
389 decoder_thread_("V4L2SliceVideoDecodeAcceleratorThread"), 390 decoder_thread_("V4L2SliceVideoDecodeAcceleratorThread"),
390 device_poll_thread_("V4L2SliceVideoDecodeAcceleratorDevicePollThread"), 391 device_poll_thread_("V4L2SliceVideoDecodeAcceleratorDevicePollThread"),
391 input_streamon_(false), 392 input_streamon_(false),
392 input_buffer_queued_count_(0), 393 input_buffer_queued_count_(0),
393 output_streamon_(false), 394 output_streamon_(false),
394 output_buffer_queued_count_(0), 395 output_buffer_queued_count_(0),
395 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN), 396 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN),
396 output_format_fourcc_(0), 397 output_format_fourcc_(0),
397 state_(kUninitialized), 398 state_(kUninitialized),
399 output_mode_(Config::OutputMode::ALLOCATE),
398 decoder_flushing_(false), 400 decoder_flushing_(false),
399 decoder_resetting_(false), 401 decoder_resetting_(false),
400 surface_set_change_pending_(false), 402 surface_set_change_pending_(false),
401 picture_clearing_count_(0), 403 picture_clearing_count_(0),
402 pictures_assigned_(false, false),
403 egl_display_(egl_display), 404 egl_display_(egl_display),
404 get_gl_context_cb_(get_gl_context_cb), 405 get_gl_context_cb_(get_gl_context_cb),
405 make_context_current_cb_(make_context_current_cb), 406 make_context_current_cb_(make_context_current_cb),
406 weak_this_factory_(this) { 407 weak_this_factory_(this) {
407 weak_this_ = weak_this_factory_.GetWeakPtr(); 408 weak_this_ = weak_this_factory_.GetWeakPtr();
408 } 409 }
409 410
410 V4L2SliceVideoDecodeAccelerator::~V4L2SliceVideoDecodeAccelerator() { 411 V4L2SliceVideoDecodeAccelerator::~V4L2SliceVideoDecodeAccelerator() {
411 DVLOGF(2); 412 DVLOGF(2);
412 413
(...skipping 18 matching lines...) Expand all
431 client_ptr_factory_.reset(); 432 client_ptr_factory_.reset();
432 } 433 }
433 } 434 }
434 435
435 bool V4L2SliceVideoDecodeAccelerator::Initialize(const Config& config, 436 bool V4L2SliceVideoDecodeAccelerator::Initialize(const Config& config,
436 Client* client) { 437 Client* client) {
437 DVLOGF(3) << "profile: " << config.profile; 438 DVLOGF(3) << "profile: " << config.profile;
438 DCHECK(child_task_runner_->BelongsToCurrentThread()); 439 DCHECK(child_task_runner_->BelongsToCurrentThread());
439 DCHECK_EQ(state_, kUninitialized); 440 DCHECK_EQ(state_, kUninitialized);
440 441
441 if (get_gl_context_cb_.is_null() || make_context_current_cb_.is_null()) { 442 if (!device_->SupportsDecodeProfileForV4L2PixelFormats(
442 NOTREACHED() << "GL callbacks are required for this VDA"; 443 config.profile, arraysize(supported_input_fourccs_),
444 supported_input_fourccs_)) {
445 DVLOGF(1) << "unsupported profile " << config.profile;
443 return false; 446 return false;
444 } 447 }
445 448
446 if (config.is_encrypted) { 449 if (config.is_encrypted) {
447 NOTREACHED() << "Encrypted streams are not supported for this VDA"; 450 NOTREACHED() << "Encrypted streams are not supported for this VDA";
448 return false; 451 return false;
449 } 452 }
450 453
451 if (!device_->SupportsDecodeProfileForV4L2PixelFormats( 454 if (config.output_mode != Config::OutputMode::ALLOCATE &&
452 config.profile, arraysize(supported_input_fourccs_), 455 config.output_mode != Config::OutputMode::IMPORT) {
453 supported_input_fourccs_)) { 456 NOTREACHED() << "Only ALLOCATE and IMPORT OutputModes are supported";
454 DVLOGF(1) << "unsupported profile " << config.profile;
455 return false; 457 return false;
456 } 458 }
457 459
458 client_ptr_factory_.reset( 460 client_ptr_factory_.reset(
459 new base::WeakPtrFactory<VideoDecodeAccelerator::Client>(client)); 461 new base::WeakPtrFactory<VideoDecodeAccelerator::Client>(client));
460 client_ = client_ptr_factory_->GetWeakPtr(); 462 client_ = client_ptr_factory_->GetWeakPtr();
461 // If we haven't been set up to decode on separate thread via 463 // If we haven't been set up to decode on separate thread via
462 // TryToSetupDecodeOnSeparateThread(), use the main thread/client for 464 // TryToSetupDecodeOnSeparateThread(), use the main thread/client for
463 // decode tasks. 465 // decode tasks.
464 if (!decode_task_runner_) { 466 if (!decode_task_runner_) {
(...skipping 20 matching lines...) Expand all
485 // TODO(posciak): This needs to be queried once supported. 487 // TODO(posciak): This needs to be queried once supported.
486 input_planes_count_ = 1; 488 input_planes_count_ = 1;
487 output_planes_count_ = 1; 489 output_planes_count_ = 1;
488 490
489 if (egl_display_ == EGL_NO_DISPLAY) { 491 if (egl_display_ == EGL_NO_DISPLAY) {
490 LOG(ERROR) << "Initialize(): could not get EGLDisplay"; 492 LOG(ERROR) << "Initialize(): could not get EGLDisplay";
491 return false; 493 return false;
492 } 494 }
493 495
494 // We need the context to be initialized to query extensions. 496 // We need the context to be initialized to query extensions.
495 if (!make_context_current_cb_.Run()) { 497 if (!make_context_current_cb_.is_null()) {
496 LOG(ERROR) << "Initialize(): could not make context current"; 498 if (!make_context_current_cb_.Run()) {
497 return false; 499 LOG(ERROR) << "Initialize(): could not make context current";
498 } 500 return false;
501 }
499 502
500 if (!gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) { 503 if (!gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) {
501 LOG(ERROR) << "Initialize(): context does not have EGL_KHR_fence_sync"; 504 LOG(ERROR) << "Initialize(): context does not have EGL_KHR_fence_sync";
502 return false; 505 return false;
506 }
507 } else {
508 DVLOG(1) << "No GL callbacks provided, initializing without GL support";
503 } 509 }
504 510
505 // Capabilities check. 511 // Capabilities check.
506 struct v4l2_capability caps; 512 struct v4l2_capability caps;
507 const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; 513 const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
508 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps); 514 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps);
509 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { 515 if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
510 LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP" 516 LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP"
511 ", caps check failed: 0x" << std::hex << caps.capabilities; 517 ", caps check failed: 0x" << std::hex << caps.capabilities;
512 return false; 518 return false;
513 } 519 }
514 520
515 if (!SetupFormats()) 521 if (!SetupFormats())
516 return false; 522 return false;
517 523
518 if (!decoder_thread_.Start()) { 524 if (!decoder_thread_.Start()) {
519 DLOG(ERROR) << "Initialize(): device thread failed to start"; 525 DLOG(ERROR) << "Initialize(): device thread failed to start";
520 return false; 526 return false;
521 } 527 }
522 decoder_thread_task_runner_ = decoder_thread_.task_runner(); 528 decoder_thread_task_runner_ = decoder_thread_.task_runner();
523 529
524 state_ = kInitialized; 530 state_ = kInitialized;
531 output_mode_ = config.output_mode;
525 532
526 // InitializeTask will NOTIFY_ERROR on failure. 533 // InitializeTask will NOTIFY_ERROR on failure.
527 decoder_thread_task_runner_->PostTask( 534 decoder_thread_task_runner_->PostTask(
528 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::InitializeTask, 535 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::InitializeTask,
529 base::Unretained(this))); 536 base::Unretained(this)));
530 537
531 DVLOGF(1) << "V4L2SliceVideoDecodeAccelerator initialized"; 538 DVLOGF(1) << "V4L2SliceVideoDecodeAccelerator initialized";
532 return true; 539 return true;
533 } 540 }
534 541
(...skipping 12 matching lines...) Expand all
547 554
548 void V4L2SliceVideoDecodeAccelerator::Destroy() { 555 void V4L2SliceVideoDecodeAccelerator::Destroy() {
549 DVLOGF(3); 556 DVLOGF(3);
550 DCHECK(child_task_runner_->BelongsToCurrentThread()); 557 DCHECK(child_task_runner_->BelongsToCurrentThread());
551 558
552 if (decoder_thread_.IsRunning()) { 559 if (decoder_thread_.IsRunning()) {
553 decoder_thread_task_runner_->PostTask( 560 decoder_thread_task_runner_->PostTask(
554 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DestroyTask, 561 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DestroyTask,
555 base::Unretained(this))); 562 base::Unretained(this)));
556 563
557 // Wake up decoder thread in case we are waiting in CreateOutputBuffers
558 // for client to provide pictures. Since this is Destroy, we won't be
559 // getting them anymore (AssignPictureBuffers won't be called).
560 pictures_assigned_.Signal();
561
562 // Wait for tasks to finish/early-exit. 564 // Wait for tasks to finish/early-exit.
563 decoder_thread_.Stop(); 565 decoder_thread_.Stop();
564 } 566 }
565 567
566 delete this; 568 delete this;
567 DVLOGF(3) << "Destroyed"; 569 DVLOGF(3) << "Destroyed";
568 } 570 }
569 571
570 void V4L2SliceVideoDecodeAccelerator::DestroyTask() { 572 void V4L2SliceVideoDecodeAccelerator::DestroyTask() {
571 DVLOGF(3); 573 DVLOGF(3);
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
753 DVLOGF(3) << "buffer_count=" << num_pictures 755 DVLOGF(3) << "buffer_count=" << num_pictures
754 << ", visible size=" << visible_size_.ToString() 756 << ", visible size=" << visible_size_.ToString()
755 << ", coded size=" << coded_size_.ToString(); 757 << ", coded size=" << coded_size_.ToString();
756 758
757 child_task_runner_->PostTask( 759 child_task_runner_->PostTask(
758 FROM_HERE, 760 FROM_HERE,
759 base::Bind(&VideoDecodeAccelerator::Client::ProvidePictureBuffers, 761 base::Bind(&VideoDecodeAccelerator::Client::ProvidePictureBuffers,
760 client_, num_pictures, 1, coded_size_, 762 client_, num_pictures, 1, coded_size_,
761 device_->GetTextureTarget())); 763 device_->GetTextureTarget()));
762 764
763 // Wait for the client to call AssignPictureBuffers() on the Child thread. 765 // Go into kAwaitingPictureBuffers to prevent us from doing any more decoding
764 // We do this, because if we continue decoding without finishing buffer 766 // or event handling while we are waiting for AssignPictureBuffers(). Not
765 // allocation, we may end up Resetting before AssignPictureBuffers arrives, 767 // having Pictures available would not have prevented us from making decoding
766 // resulting in unnecessary complications and subtle bugs. 768 // progress entirely e.g. in the case of H.264 where we could further decode
767 pictures_assigned_.Wait(); 769 // non-slice NALUs and could even get another resolution change before we were
768 770 // done with this one. After we get the buffers, we'll go back into kIdle and
771 // kick off further event processing, and eventually go back into kDecoding
772 // once no more events are pending (if any).
773 state_ = kAwaitingPictureBuffers;
769 return true; 774 return true;
770 } 775 }
771 776
772 void V4L2SliceVideoDecodeAccelerator::DestroyInputBuffers() { 777 void V4L2SliceVideoDecodeAccelerator::DestroyInputBuffers() {
773 DVLOGF(3); 778 DVLOGF(3);
774 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread() || 779 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread() ||
775 !decoder_thread_.IsRunning()); 780 !decoder_thread_.IsRunning());
776 DCHECK(!input_streamon_); 781 DCHECK(!input_streamon_);
777 782
778 for (auto& input_record : input_buffer_map_) { 783 for (auto& input_record : input_buffer_map_) {
779 if (input_record.address != nullptr) 784 if (input_record.address != nullptr)
780 device_->Munmap(input_record.address, input_record.length); 785 device_->Munmap(input_record.address, input_record.length);
781 } 786 }
782 787
783 struct v4l2_requestbuffers reqbufs; 788 struct v4l2_requestbuffers reqbufs;
784 memset(&reqbufs, 0, sizeof(reqbufs)); 789 memset(&reqbufs, 0, sizeof(reqbufs));
785 reqbufs.count = 0; 790 reqbufs.count = 0;
786 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 791 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
787 reqbufs.memory = V4L2_MEMORY_MMAP; 792 reqbufs.memory = V4L2_MEMORY_MMAP;
788 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); 793 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
789 794
790 input_buffer_map_.clear(); 795 input_buffer_map_.clear();
791 free_input_buffers_.clear(); 796 free_input_buffers_.clear();
792 } 797 }
793 798
794 void V4L2SliceVideoDecodeAccelerator::DismissPictures( 799 void V4L2SliceVideoDecodeAccelerator::DismissPictures(
795 std::vector<int32_t> picture_buffer_ids, 800 const std::vector<int32_t>& picture_buffer_ids,
796 base::WaitableEvent* done) { 801 base::WaitableEvent* done) {
797 DVLOGF(3); 802 DVLOGF(3);
798 DCHECK(child_task_runner_->BelongsToCurrentThread()); 803 DCHECK(child_task_runner_->BelongsToCurrentThread());
799 804
800 for (auto picture_buffer_id : picture_buffer_ids) { 805 for (auto picture_buffer_id : picture_buffer_ids) {
801 DVLOGF(1) << "dismissing PictureBuffer id=" << picture_buffer_id; 806 DVLOGF(1) << "dismissing PictureBuffer id=" << picture_buffer_id;
802 client_->DismissPictureBuffer(picture_buffer_id); 807 client_->DismissPictureBuffer(picture_buffer_id);
803 } 808 }
804 809
805 done->Signal(); 810 done->Signal();
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
899 DVLOGF(3); 904 DVLOGF(3);
900 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 905 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
901 906
902 struct v4l2_buffer dqbuf; 907 struct v4l2_buffer dqbuf;
903 struct v4l2_plane planes[VIDEO_MAX_PLANES]; 908 struct v4l2_plane planes[VIDEO_MAX_PLANES];
904 while (input_buffer_queued_count_ > 0) { 909 while (input_buffer_queued_count_ > 0) {
905 DCHECK(input_streamon_); 910 DCHECK(input_streamon_);
906 memset(&dqbuf, 0, sizeof(dqbuf)); 911 memset(&dqbuf, 0, sizeof(dqbuf));
907 memset(&planes, 0, sizeof(planes)); 912 memset(&planes, 0, sizeof(planes));
908 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 913 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
909 dqbuf.memory = V4L2_MEMORY_USERPTR; 914 dqbuf.memory = V4L2_MEMORY_MMAP;
910 dqbuf.m.planes = planes; 915 dqbuf.m.planes = planes;
911 dqbuf.length = input_planes_count_; 916 dqbuf.length = input_planes_count_;
912 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { 917 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
913 if (errno == EAGAIN) { 918 if (errno == EAGAIN) {
914 // EAGAIN if we're just out of buffers to dequeue. 919 // EAGAIN if we're just out of buffers to dequeue.
915 break; 920 break;
916 } 921 }
917 PLOG(ERROR) << "ioctl() failed: VIDIOC_DQBUF"; 922 PLOG(ERROR) << "ioctl() failed: VIDIOC_DQBUF";
918 NOTIFY_ERROR(PLATFORM_FAILURE); 923 NOTIFY_ERROR(PLATFORM_FAILURE);
919 return; 924 return;
920 } 925 }
921 InputRecord& input_record = input_buffer_map_[dqbuf.index]; 926 InputRecord& input_record = input_buffer_map_[dqbuf.index];
922 DCHECK(input_record.at_device); 927 DCHECK(input_record.at_device);
923 input_record.at_device = false; 928 input_record.at_device = false;
924 ReuseInputBuffer(dqbuf.index); 929 ReuseInputBuffer(dqbuf.index);
925 input_buffer_queued_count_--; 930 input_buffer_queued_count_--;
926 DVLOGF(4) << "Dequeued input=" << dqbuf.index 931 DVLOGF(4) << "Dequeued input=" << dqbuf.index
927 << " count: " << input_buffer_queued_count_; 932 << " count: " << input_buffer_queued_count_;
928 } 933 }
929 934
930 while (output_buffer_queued_count_ > 0) { 935 while (output_buffer_queued_count_ > 0) {
931 DCHECK(output_streamon_); 936 DCHECK(output_streamon_);
932 memset(&dqbuf, 0, sizeof(dqbuf)); 937 memset(&dqbuf, 0, sizeof(dqbuf));
933 memset(&planes, 0, sizeof(planes)); 938 memset(&planes, 0, sizeof(planes));
934 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 939 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
935 dqbuf.memory = V4L2_MEMORY_MMAP; 940 dqbuf.memory =
941 (output_mode_ == Config::OutputMode::ALLOCATE ? V4L2_MEMORY_MMAP
942 : V4L2_MEMORY_DMABUF);
936 dqbuf.m.planes = planes; 943 dqbuf.m.planes = planes;
937 dqbuf.length = output_planes_count_; 944 dqbuf.length = output_planes_count_;
938 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { 945 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
939 if (errno == EAGAIN) { 946 if (errno == EAGAIN) {
940 // EAGAIN if we're just out of buffers to dequeue. 947 // EAGAIN if we're just out of buffers to dequeue.
941 break; 948 break;
942 } 949 }
943 PLOG(ERROR) << "ioctl() failed: VIDIOC_DQBUF"; 950 PLOG(ERROR) << "ioctl() failed: VIDIOC_DQBUF";
944 NOTIFY_ERROR(PLATFORM_FAILURE); 951 NOTIFY_ERROR(PLATFORM_FAILURE);
945 return; 952 return;
(...skipping 15 matching lines...) Expand all
961 it->second->SetDecoded(); 968 it->second->SetDecoded();
962 surfaces_at_device_.erase(it); 969 surfaces_at_device_.erase(it);
963 } 970 }
964 971
965 // A frame was decoded, see if we can output it. 972 // A frame was decoded, see if we can output it.
966 TryOutputSurfaces(); 973 TryOutputSurfaces();
967 974
968 ProcessPendingEventsIfNeeded(); 975 ProcessPendingEventsIfNeeded();
969 } 976 }
970 977
978 void V4L2SliceVideoDecodeAccelerator::NewEventPending() {
979 // Switch to event processing mode if we are decoding. Otherwise we are either
980 // already in it, or we will potentially switch to it later, after finishing
981 // other tasks.
982 if (state_ == kDecoding)
983 state_ = kIdle;
984
985 ProcessPendingEventsIfNeeded();
986 }
987
988 bool V4L2SliceVideoDecodeAccelerator::FinishEventProcessing() {
989 DCHECK_EQ(state_, kIdle);
990
991 state_ = kDecoding;
992 ScheduleDecodeBufferTaskIfNeeded();
993
994 return true;
995 }
996
971 void V4L2SliceVideoDecodeAccelerator::ProcessPendingEventsIfNeeded() { 997 void V4L2SliceVideoDecodeAccelerator::ProcessPendingEventsIfNeeded() {
998 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
999
972 // Process pending events, if any, in the correct order. 1000 // Process pending events, if any, in the correct order.
973 // We always first process the surface set change, as it is an internal 1001 // We always first process the surface set change, as it is an internal
974 // event from the decoder and interleaving it with external requests would 1002 // event from the decoder and interleaving it with external requests would
975 // put the decoder in an undefined state. 1003 // put the decoder in an undefined state.
976 FinishSurfaceSetChangeIfNeeded(); 1004 using ProcessFunc = bool (V4L2SliceVideoDecodeAccelerator::*)();
1005 const ProcessFunc process_functions[] = {
1006 &V4L2SliceVideoDecodeAccelerator::FinishSurfaceSetChange,
1007 &V4L2SliceVideoDecodeAccelerator::FinishFlush,
1008 &V4L2SliceVideoDecodeAccelerator::FinishReset,
1009 &V4L2SliceVideoDecodeAccelerator::FinishEventProcessing,
1010 };
977 1011
978 // Process external (client) requests. 1012 for (const auto& fn : process_functions) {
979 FinishFlushIfNeeded(); 1013 if (state_ != kIdle)
980 FinishResetIfNeeded(); 1014 return;
1015
1016 if (!(this->*fn)())
1017 return;
1018 }
981 } 1019 }
982 1020
983 void V4L2SliceVideoDecodeAccelerator::ReuseInputBuffer(int index) { 1021 void V4L2SliceVideoDecodeAccelerator::ReuseInputBuffer(int index) {
984 DVLOGF(4) << "Reusing input buffer, index=" << index; 1022 DVLOGF(4) << "Reusing input buffer, index=" << index;
985 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 1023 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
986 1024
987 DCHECK_LT(index, static_cast<int>(input_buffer_map_.size())); 1025 DCHECK_LT(index, static_cast<int>(input_buffer_map_.size()));
988 InputRecord& input_record = input_buffer_map_[index]; 1026 InputRecord& input_record = input_buffer_map_[index];
989 1027
990 DCHECK(!input_record.at_device); 1028 DCHECK(!input_record.at_device);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1043 } 1081 }
1044 1082
1045 bool V4L2SliceVideoDecodeAccelerator::EnqueueOutputRecord(int index) { 1083 bool V4L2SliceVideoDecodeAccelerator::EnqueueOutputRecord(int index) {
1046 DVLOGF(3); 1084 DVLOGF(3);
1047 DCHECK_LT(index, static_cast<int>(output_buffer_map_.size())); 1085 DCHECK_LT(index, static_cast<int>(output_buffer_map_.size()));
1048 1086
1049 // Enqueue an output (VIDEO_CAPTURE) buffer. 1087 // Enqueue an output (VIDEO_CAPTURE) buffer.
1050 OutputRecord& output_record = output_buffer_map_[index]; 1088 OutputRecord& output_record = output_buffer_map_[index];
1051 DCHECK(!output_record.at_device); 1089 DCHECK(!output_record.at_device);
1052 DCHECK(!output_record.at_client); 1090 DCHECK(!output_record.at_client);
1053 DCHECK_NE(output_record.egl_image, EGL_NO_IMAGE_KHR);
1054 DCHECK_NE(output_record.picture_id, -1); 1091 DCHECK_NE(output_record.picture_id, -1);
1055 1092
1056 if (output_record.egl_sync != EGL_NO_SYNC_KHR) { 1093 if (output_record.egl_sync != EGL_NO_SYNC_KHR) {
1057 // If we have to wait for completion, wait. Note that 1094 // If we have to wait for completion, wait. Note that
1058 // free_output_buffers_ is a FIFO queue, so we always wait on the 1095 // free_output_buffers_ is a FIFO queue, so we always wait on the
1059 // buffer that has been in the queue the longest. 1096 // buffer that has been in the queue the longest.
1060 if (eglClientWaitSyncKHR(egl_display_, output_record.egl_sync, 0, 1097 if (eglClientWaitSyncKHR(egl_display_, output_record.egl_sync, 0,
1061 EGL_FOREVER_KHR) == EGL_FALSE) { 1098 EGL_FOREVER_KHR) == EGL_FALSE) {
1062 // This will cause tearing, but is safe otherwise. 1099 // This will cause tearing, but is safe otherwise.
1063 DVLOGF(1) << "eglClientWaitSyncKHR failed!"; 1100 DVLOGF(1) << "eglClientWaitSyncKHR failed!";
1064 } 1101 }
1065 if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) { 1102 if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) {
1066 LOGF(ERROR) << "eglDestroySyncKHR failed!"; 1103 LOGF(ERROR) << "eglDestroySyncKHR failed!";
1067 NOTIFY_ERROR(PLATFORM_FAILURE); 1104 NOTIFY_ERROR(PLATFORM_FAILURE);
1068 return false; 1105 return false;
1069 } 1106 }
1070 output_record.egl_sync = EGL_NO_SYNC_KHR; 1107 output_record.egl_sync = EGL_NO_SYNC_KHR;
1071 } 1108 }
1072 1109
1073 struct v4l2_buffer qbuf; 1110 struct v4l2_buffer qbuf;
1074 struct v4l2_plane qbuf_planes[VIDEO_MAX_PLANES]; 1111 struct v4l2_plane qbuf_planes[VIDEO_MAX_PLANES];
1075 memset(&qbuf, 0, sizeof(qbuf)); 1112 memset(&qbuf, 0, sizeof(qbuf));
1076 memset(qbuf_planes, 0, sizeof(qbuf_planes)); 1113 memset(qbuf_planes, 0, sizeof(qbuf_planes));
1077 qbuf.index = index; 1114 qbuf.index = index;
1078 qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1115 qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1079 qbuf.memory = V4L2_MEMORY_MMAP; 1116 if (output_mode_ == Config::OutputMode::ALLOCATE) {
1117 qbuf.memory = V4L2_MEMORY_MMAP;
1118 } else {
1119 qbuf.memory = V4L2_MEMORY_DMABUF;
1120 DCHECK_EQ(output_planes_count_, output_record.dmabuf_fds.size());
1121 for (size_t i = 0; i < output_record.dmabuf_fds.size(); ++i) {
1122 DCHECK(output_record.dmabuf_fds[i].is_valid());
1123 qbuf_planes[i].m.fd = output_record.dmabuf_fds[i].get();
1124 }
1125 }
1080 qbuf.m.planes = qbuf_planes; 1126 qbuf.m.planes = qbuf_planes;
1081 qbuf.length = output_planes_count_; 1127 qbuf.length = output_planes_count_;
1082 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf); 1128 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
1083 output_record.at_device = true; 1129 output_record.at_device = true;
1084 output_buffer_queued_count_++; 1130 output_buffer_queued_count_++;
1085 DVLOGF(4) << "Enqueued output=" << qbuf.index 1131 DVLOGF(4) << "Enqueued output=" << qbuf.index
1086 << " count: " << output_buffer_queued_count_; 1132 << " count: " << output_buffer_queued_count_;
1087 1133
1088 return true; 1134 return true;
1089 } 1135 }
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
1295 DVLOGF(1) << "Error decoding stream"; 1341 DVLOGF(1) << "Error decoding stream";
1296 NOTIFY_ERROR(PLATFORM_FAILURE); 1342 NOTIFY_ERROR(PLATFORM_FAILURE);
1297 return; 1343 return;
1298 } 1344 }
1299 } 1345 }
1300 } 1346 }
1301 1347
1302 void V4L2SliceVideoDecodeAccelerator::InitiateSurfaceSetChange() { 1348 void V4L2SliceVideoDecodeAccelerator::InitiateSurfaceSetChange() {
1303 DVLOGF(2); 1349 DVLOGF(2);
1304 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 1350 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1305
1306 DCHECK_EQ(state_, kDecoding); 1351 DCHECK_EQ(state_, kDecoding);
1307 state_ = kIdle;
1308 1352
1309 DCHECK(!surface_set_change_pending_); 1353 DCHECK(!surface_set_change_pending_);
1310 surface_set_change_pending_ = true; 1354 surface_set_change_pending_ = true;
1311 1355 NewEventPending();
1312 FinishSurfaceSetChangeIfNeeded();
1313 } 1356 }
1314 1357
1315 void V4L2SliceVideoDecodeAccelerator::FinishSurfaceSetChangeIfNeeded() { 1358 bool V4L2SliceVideoDecodeAccelerator::FinishSurfaceSetChange() {
1316 DVLOGF(2); 1359 DVLOGF(2);
1317 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 1360 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1318 1361
1319 if (!surface_set_change_pending_ || !surfaces_at_device_.empty()) 1362 if (!surface_set_change_pending_)
1320 return; 1363 return true;
1364
1365 if (!surfaces_at_device_.empty())
1366 return false;
1321 1367
1322 DCHECK_EQ(state_, kIdle); 1368 DCHECK_EQ(state_, kIdle);
1323 DCHECK(decoder_display_queue_.empty()); 1369 DCHECK(decoder_display_queue_.empty());
1324 // All output buffers should've been returned from decoder and device by now. 1370 // All output buffers should've been returned from decoder and device by now.
1325 // The only remaining owner of surfaces may be display (client), and we will 1371 // The only remaining owner of surfaces may be display (client), and we will
1326 // dismiss them when destroying output buffers below. 1372 // dismiss them when destroying output buffers below.
1327 DCHECK_EQ(free_output_buffers_.size() + surfaces_at_display_.size(), 1373 DCHECK_EQ(free_output_buffers_.size() + surfaces_at_display_.size(),
1328 output_buffer_map_.size()); 1374 output_buffer_map_.size());
1329 1375
1330 // Keep input queue running while we switch outputs. 1376 // Keep input queue running while we switch outputs.
1331 if (!StopDevicePoll(true)) { 1377 if (!StopDevicePoll(true)) {
1332 NOTIFY_ERROR(PLATFORM_FAILURE); 1378 NOTIFY_ERROR(PLATFORM_FAILURE);
1333 return; 1379 return false;
1334 } 1380 }
1335 1381
1336 // This will return only once all buffers are dismissed and destroyed. 1382 // This will return only once all buffers are dismissed and destroyed.
1337 // This does not wait until they are displayed however, as display retains 1383 // This does not wait until they are displayed however, as display retains
1338 // references to the buffers bound to textures and will release them 1384 // references to the buffers bound to textures and will release them
1339 // after displaying. 1385 // after displaying.
1340 if (!DestroyOutputs(true)) { 1386 if (!DestroyOutputs(true)) {
1341 NOTIFY_ERROR(PLATFORM_FAILURE); 1387 NOTIFY_ERROR(PLATFORM_FAILURE);
1342 return; 1388 return false;
1343 } 1389 }
1344 1390
1345 if (!CreateOutputBuffers()) { 1391 if (!CreateOutputBuffers()) {
1346 NOTIFY_ERROR(PLATFORM_FAILURE); 1392 NOTIFY_ERROR(PLATFORM_FAILURE);
1347 return; 1393 return false;
1348 } 1394 }
1349 1395
1350 if (!StartDevicePoll()) {
1351 NOTIFY_ERROR(PLATFORM_FAILURE);
1352 return;
1353 }
1354
1355 DVLOGF(3) << "Surface set change finished";
1356
1357 surface_set_change_pending_ = false; 1396 surface_set_change_pending_ = false;
1358 state_ = kDecoding; 1397 DVLOG(3) << "Surface set change finished";
1359 ScheduleDecodeBufferTaskIfNeeded(); 1398 return true;
1360 } 1399 }
1361 1400
1362 bool V4L2SliceVideoDecodeAccelerator::DestroyOutputs(bool dismiss) { 1401 bool V4L2SliceVideoDecodeAccelerator::DestroyOutputs(bool dismiss) {
1363 DVLOGF(3); 1402 DVLOGF(3);
1364 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 1403 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1365 std::vector<EGLImageKHR> egl_images_to_destroy;
1366 std::vector<int32_t> picture_buffers_to_dismiss; 1404 std::vector<int32_t> picture_buffers_to_dismiss;
1367 1405
1368 if (output_buffer_map_.empty()) 1406 if (output_buffer_map_.empty())
1369 return true; 1407 return true;
1370 1408
1371 for (auto output_record : output_buffer_map_) { 1409 for (const auto& output_record : output_buffer_map_) {
1372 DCHECK(!output_record.at_device); 1410 DCHECK(!output_record.at_device);
1373 1411
1374 if (output_record.egl_sync != EGL_NO_SYNC_KHR) { 1412 if (output_record.egl_sync != EGL_NO_SYNC_KHR) {
1375 if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) 1413 if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE)
1376 DVLOGF(1) << "eglDestroySyncKHR failed."; 1414 DVLOGF(1) << "eglDestroySyncKHR failed.";
1377 } 1415 }
1378 1416
1379 if (output_record.egl_image != EGL_NO_IMAGE_KHR) { 1417 if (output_record.egl_image != EGL_NO_IMAGE_KHR) {
1380 child_task_runner_->PostTask( 1418 child_task_runner_->PostTask(
1381 FROM_HERE, 1419 FROM_HERE,
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1439 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); 1477 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs);
1440 1478
1441 return true; 1479 return true;
1442 } 1480 }
1443 1481
1444 void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffers( 1482 void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffers(
1445 const std::vector<media::PictureBuffer>& buffers) { 1483 const std::vector<media::PictureBuffer>& buffers) {
1446 DVLOGF(3); 1484 DVLOGF(3);
1447 DCHECK(child_task_runner_->BelongsToCurrentThread()); 1485 DCHECK(child_task_runner_->BelongsToCurrentThread());
1448 1486
1487 decoder_thread_task_runner_->PostTask(
1488 FROM_HERE,
1489 base::Bind(&V4L2SliceVideoDecodeAccelerator::AssignPictureBuffersTask,
1490 base::Unretained(this), buffers));
1491 }
1492
1493 void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffersTask(
1494 const std::vector<media::PictureBuffer>& buffers) {
1495 DVLOGF(3);
1496 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1497 DCHECK_EQ(state_, kAwaitingPictureBuffers);
1498
1449 const uint32_t req_buffer_count = decoder_->GetRequiredNumOfPictures(); 1499 const uint32_t req_buffer_count = decoder_->GetRequiredNumOfPictures();
1450 1500
1451 if (buffers.size() < req_buffer_count) { 1501 if (buffers.size() < req_buffer_count) {
1452 DLOG(ERROR) << "Failed to provide requested picture buffers. " 1502 DLOG(ERROR) << "Failed to provide requested picture buffers. "
1453 << "(Got " << buffers.size() 1503 << "(Got " << buffers.size()
1454 << ", requested " << req_buffer_count << ")"; 1504 << ", requested " << req_buffer_count << ")";
1455 NOTIFY_ERROR(INVALID_ARGUMENT); 1505 NOTIFY_ERROR(INVALID_ARGUMENT);
1456 return; 1506 return;
1457 } 1507 }
1458 1508
1459 gfx::GLContext* gl_context = get_gl_context_cb_.Run();
1460 if (!gl_context || !make_context_current_cb_.Run()) {
1461 DLOG(ERROR) << "No GL context";
1462 NOTIFY_ERROR(PLATFORM_FAILURE);
1463 return;
1464 }
1465
1466 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0);
1467
1468 // It's safe to manipulate all the buffer state here, because the decoder
1469 // thread is waiting on pictures_assigned_.
1470
1471 // Allocate the output buffers. 1509 // Allocate the output buffers.
1472 struct v4l2_requestbuffers reqbufs; 1510 struct v4l2_requestbuffers reqbufs;
1473 memset(&reqbufs, 0, sizeof(reqbufs)); 1511 memset(&reqbufs, 0, sizeof(reqbufs));
1474 reqbufs.count = buffers.size(); 1512 reqbufs.count = buffers.size();
1475 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1513 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1476 reqbufs.memory = V4L2_MEMORY_MMAP; 1514 reqbufs.memory =
1515 (output_mode_ == Config::OutputMode::ALLOCATE ? V4L2_MEMORY_MMAP
1516 : V4L2_MEMORY_DMABUF);
1477 IOCTL_OR_ERROR_RETURN(VIDIOC_REQBUFS, &reqbufs); 1517 IOCTL_OR_ERROR_RETURN(VIDIOC_REQBUFS, &reqbufs);
1478 1518
1479 if (reqbufs.count != buffers.size()) { 1519 if (reqbufs.count != buffers.size()) {
1480 DLOG(ERROR) << "Could not allocate enough output buffers"; 1520 DLOG(ERROR) << "Could not allocate enough output buffers";
1481 NOTIFY_ERROR(PLATFORM_FAILURE); 1521 NOTIFY_ERROR(PLATFORM_FAILURE);
1482 return; 1522 return;
1483 } 1523 }
1484 1524
1525 DCHECK(free_output_buffers_.empty());
1526 DCHECK(output_buffer_map_.empty());
1485 output_buffer_map_.resize(buffers.size()); 1527 output_buffer_map_.resize(buffers.size());
1486
1487 DCHECK(free_output_buffers_.empty());
1488 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { 1528 for (size_t i = 0; i < output_buffer_map_.size(); ++i) {
1489 DCHECK(buffers[i].size() == coded_size_); 1529 DCHECK(buffers[i].size() == coded_size_);
1530 DCHECK_EQ(1u, buffers[i].texture_ids().size());
1490 1531
1491 OutputRecord& output_record = output_buffer_map_[i]; 1532 OutputRecord& output_record = output_buffer_map_[i];
1492 DCHECK(!output_record.at_device); 1533 DCHECK(!output_record.at_device);
1493 DCHECK(!output_record.at_client); 1534 DCHECK(!output_record.at_client);
1494 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); 1535 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR);
1495 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); 1536 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR);
1496 DCHECK_EQ(output_record.picture_id, -1); 1537 DCHECK_EQ(output_record.picture_id, -1);
1538 DCHECK(output_record.dmabuf_fds.empty());
1497 DCHECK_EQ(output_record.cleared, false); 1539 DCHECK_EQ(output_record.cleared, false);
1498 1540
1499 DCHECK_LE(1u, buffers[i].texture_ids().size()); 1541 output_record.picture_id = buffers[i].id();
1500 EGLImageKHR egl_image = device_->CreateEGLImage( 1542 output_record.texture_id = buffers[i].texture_ids()[0];
1501 egl_display_, gl_context->GetHandle(), buffers[i].texture_ids()[0], 1543 // This will remain true until ImportBufferForPicture is called, either by
1502 buffers[i].size(), i, output_format_fourcc_, output_planes_count_); 1544 // the client, or by ourselves, if we are allocating.
1503 if (egl_image == EGL_NO_IMAGE_KHR) { 1545 output_record.at_client = true;
1504 LOGF(ERROR) << "Could not create EGLImageKHR"; 1546 if (output_mode_ == Config::OutputMode::ALLOCATE) {
1505 // Ownership of EGLImages allocated in previous iterations of this loop 1547 std::vector<base::ScopedFD> dmabuf_fds =
1506 // has been transferred to output_buffer_map_. After we error-out here 1548 std::move(device_->GetDmabufsForV4L2Buffer(
1507 // the destructor will handle their cleanup. 1549 i, output_planes_count_, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE));
1508 NOTIFY_ERROR(PLATFORM_FAILURE); 1550 if (dmabuf_fds.empty()) {
1509 return; 1551 NOTIFY_ERROR(PLATFORM_FAILURE);
1552 return;
1553 }
1554
1555 auto passed_dmabuf_fds(base::WrapUnique(
1556 new std::vector<base::ScopedFD>(std::move(dmabuf_fds))));
1557 ImportBufferForPictureTask(output_record.picture_id,
1558 std::move(passed_dmabuf_fds));
1559 } // else we'll get triggered via ImportBufferForPicture() from client.
1560 DVLOGF(3) << "buffer[" << i << "]: picture_id=" << output_record.picture_id;
1561 }
1562
1563 if (!StartDevicePoll()) {
1564 NOTIFY_ERROR(PLATFORM_FAILURE);
1565 return;
1566 }
1567
1568 // Put us in kIdle to allow further event processing.
1569 // ProcessPendingEventsIfNeeded() will put us back into kDecoding after all
1570 // other pending events are processed successfully.
1571 state_ = kIdle;
1572 ProcessPendingEventsIfNeeded();
1573 }
1574
1575 void V4L2SliceVideoDecodeAccelerator::CreateEGLImageFor(
1576 size_t buffer_index,
1577 int32_t picture_buffer_id,
1578 std::unique_ptr<std::vector<base::ScopedFD>> passed_dmabuf_fds,
1579 GLuint texture_id,
1580 const gfx::Size& size,
1581 uint32_t fourcc) {
1582 DVLOGF(3) << "index=" << buffer_index;
1583 DCHECK(child_task_runner_->BelongsToCurrentThread());
1584
1585 if (get_gl_context_cb_.is_null() || make_context_current_cb_.is_null()) {
1586 DLOG(ERROR) << "GL callbacks required for binding to EGLImages";
1587 NOTIFY_ERROR(INVALID_ARGUMENT);
1588 return;
1589 }
1590
1591 gfx::GLContext* gl_context = get_gl_context_cb_.Run();
1592 if (!gl_context || !make_context_current_cb_.Run()) {
1593 DLOG(ERROR) << "No GL context";
1594 NOTIFY_ERROR(PLATFORM_FAILURE);
1595 return;
1596 }
1597
1598 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0);
1599
1600 EGLImageKHR egl_image =
1601 device_->CreateEGLImage(egl_display_, gl_context->GetHandle(), texture_id,
1602 size, buffer_index, fourcc, *passed_dmabuf_fds);
1603 if (egl_image == EGL_NO_IMAGE_KHR) {
1604 LOGF(ERROR) << "Could not create EGLImageKHR,"
1605 << " index=" << buffer_index << " texture_id=" << texture_id;
1606 NOTIFY_ERROR(PLATFORM_FAILURE);
1607 return;
1608 }
1609
1610 decoder_thread_task_runner_->PostTask(
1611 FROM_HERE,
1612 base::Bind(&V4L2SliceVideoDecodeAccelerator::AssignEGLImage,
1613 base::Unretained(this), buffer_index, picture_buffer_id,
1614 egl_image, base::Passed(&passed_dmabuf_fds)));
1615 }
1616
1617 void V4L2SliceVideoDecodeAccelerator::AssignEGLImage(
1618 size_t buffer_index,
1619 int32_t picture_buffer_id,
1620 EGLImageKHR egl_image,
1621 std::unique_ptr<std::vector<base::ScopedFD>> passed_dmabuf_fds) {
1622 DVLOGF(3) << "index=" << buffer_index;
1623 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1624
1625 // It's possible that while waiting for the EGLImages to be allocated and
1626 // assigned, we have already decoded more of the stream and saw another
1627 // resolution change. This is a normal situation, in such a case either there
1628 // is no output record with this index awaiting an EGLImage to be assigned to
1629 // it, or the record is already updated to use a newer PictureBuffer and is
1630 // awaiting an EGLImage associated with a different picture_buffer_id. If so,
1631 // just discard this image, we will get the one we are waiting for later.
1632 if (buffer_index >= output_buffer_map_.size() ||
1633 output_buffer_map_[buffer_index].picture_id != picture_buffer_id) {
1634 DVLOGF(3) << "Picture set already changed, dropping EGLImage";
1635 child_task_runner_->PostTask(
1636 FROM_HERE, base::Bind(base::IgnoreResult(&V4L2Device::DestroyEGLImage),
1637 device_, egl_display_, egl_image));
1638 return;
1639 }
1640
1641 OutputRecord& output_record = output_buffer_map_[buffer_index];
1642 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR);
1643 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR);
1644 DCHECK(!output_record.at_client);
1645 DCHECK(!output_record.at_device);
1646
1647 output_record.egl_image = egl_image;
1648 if (output_mode_ == Config::OutputMode::IMPORT) {
1649 DCHECK(output_record.dmabuf_fds.empty());
1650 output_record.dmabuf_fds = std::move(*passed_dmabuf_fds);
1651 }
1652
1653 DCHECK_EQ(std::count(free_output_buffers_.begin(), free_output_buffers_.end(),
1654 buffer_index),
1655 0);
1656 free_output_buffers_.push_back(buffer_index);
1657 ScheduleDecodeBufferTaskIfNeeded();
1658 }
1659
1660 void V4L2SliceVideoDecodeAccelerator::ImportBufferForPicture(
1661 int32_t picture_buffer_id,
1662 const std::vector<gfx::GpuMemoryBufferHandle>& gpu_memory_buffer_handles) {
1663 DVLOGF(3) << "picture_buffer_id=" << picture_buffer_id;
1664 DCHECK(child_task_runner_->BelongsToCurrentThread());
1665
1666 auto passed_dmabuf_fds(base::WrapUnique(new std::vector<base::ScopedFD>()));
1667 for (const auto& handle : gpu_memory_buffer_handles) {
1668 int fd = -1;
1669 #if defined(USE_OZONE)
1670 fd = handle.native_pixmap_handle.fd.fd;
1671 #endif
1672 DCHECK_NE(fd, -1);
1673 passed_dmabuf_fds->push_back(base::ScopedFD(fd));
1674 }
1675
1676 if (output_mode_ != Config::OutputMode::IMPORT) {
1677 LOGF(ERROR) << "Cannot import in non-import mode";
1678 NOTIFY_ERROR(INVALID_ARGUMENT);
1679 return;
1680 }
1681
1682 decoder_thread_task_runner_->PostTask(
1683 FROM_HERE,
1684 base::Bind(&V4L2SliceVideoDecodeAccelerator::ImportBufferForPictureTask,
1685 base::Unretained(this), picture_buffer_id,
1686 base::Passed(&passed_dmabuf_fds)));
1687 }
1688
1689 void V4L2SliceVideoDecodeAccelerator::ImportBufferForPictureTask(
1690 int32_t picture_buffer_id,
1691 std::unique_ptr<std::vector<base::ScopedFD>> passed_dmabuf_fds) {
1692 DVLOGF(3) << "picture_buffer_id=" << picture_buffer_id;
1693 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1694
1695 const auto iter =
1696 std::find_if(output_buffer_map_.begin(), output_buffer_map_.end(),
1697 [picture_buffer_id](const OutputRecord& output_record) {
1698 return output_record.picture_id == picture_buffer_id;
1699 });
1700 if (iter == output_buffer_map_.end()) {
1701 LOGF(ERROR) << "Invalid picture_buffer_id=" << picture_buffer_id;
1702 NOTIFY_ERROR(INVALID_ARGUMENT);
1703 return;
1704 }
1705
1706 if (!iter->at_client) {
1707 LOGF(ERROR) << "Cannot import buffer that not owned by client";
1708 NOTIFY_ERROR(INVALID_ARGUMENT);
1709 return;
1710 }
1711
1712 size_t index = iter - output_buffer_map_.begin();
1713 DCHECK_EQ(std::count(free_output_buffers_.begin(), free_output_buffers_.end(),
1714 index),
1715 0);
1716
1717 DCHECK(!iter->at_device);
1718 iter->at_client = false;
1719 if (iter->texture_id != 0) {
1720 if (iter->egl_image != EGL_NO_IMAGE_KHR) {
1721 child_task_runner_->PostTask(
1722 FROM_HERE,
1723 base::Bind(base::IgnoreResult(&V4L2Device::DestroyEGLImage), device_,
1724 egl_display_, iter->egl_image));
1510 } 1725 }
1511 1726
1512 output_record.egl_image = egl_image; 1727 child_task_runner_->PostTask(
1513 output_record.picture_id = buffers[i].id(); 1728 FROM_HERE,
1514 free_output_buffers_.push_back(i); 1729 base::Bind(&V4L2SliceVideoDecodeAccelerator::CreateEGLImageFor,
1515 DVLOGF(3) << "buffer[" << i << "]: picture_id=" << output_record.picture_id; 1730 weak_this_, index, picture_buffer_id,
1516 } 1731 base::Passed(&passed_dmabuf_fds), iter->texture_id,
1517 1732 coded_size_, output_format_fourcc_));
1518 pictures_assigned_.Signal(); 1733 } else {
1734 // No need for an EGLImage, start using this buffer now.
1735 DCHECK_EQ(output_planes_count_, passed_dmabuf_fds->size());
1736 iter->dmabuf_fds.swap(*passed_dmabuf_fds);
1737 free_output_buffers_.push_back(index);
1738 ScheduleDecodeBufferTaskIfNeeded();
1739 }
1519 } 1740 }
1520 1741
1521 void V4L2SliceVideoDecodeAccelerator::ReusePictureBuffer( 1742 void V4L2SliceVideoDecodeAccelerator::ReusePictureBuffer(
1522 int32_t picture_buffer_id) { 1743 int32_t picture_buffer_id) {
1523 DCHECK(child_task_runner_->BelongsToCurrentThread()); 1744 DCHECK(child_task_runner_->BelongsToCurrentThread());
1524 DVLOGF(4) << "picture_buffer_id=" << picture_buffer_id; 1745 DVLOGF(4) << "picture_buffer_id=" << picture_buffer_id;
1525 1746
1526 if (!make_context_current_cb_.Run()) { 1747 std::unique_ptr<EGLSyncKHRRef> egl_sync_ref;
1527 LOGF(ERROR) << "could not make context current"; 1748
1528 NOTIFY_ERROR(PLATFORM_FAILURE); 1749 if (!make_context_current_cb_.is_null()) {
1529 return; 1750 if (!make_context_current_cb_.Run()) {
1530 } 1751 LOGF(ERROR) << "could not make context current";
1531 1752 NOTIFY_ERROR(PLATFORM_FAILURE);
1532 EGLSyncKHR egl_sync = 1753 return;
1533 eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); 1754 }
1534 if (egl_sync == EGL_NO_SYNC_KHR) { 1755
1535 LOGF(ERROR) << "eglCreateSyncKHR() failed"; 1756 EGLSyncKHR egl_sync =
1536 NOTIFY_ERROR(PLATFORM_FAILURE); 1757 eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL);
1537 return; 1758 if (egl_sync == EGL_NO_SYNC_KHR) {
1538 } 1759 LOGF(ERROR) << "eglCreateSyncKHR() failed";
1539 1760 NOTIFY_ERROR(PLATFORM_FAILURE);
1540 std::unique_ptr<EGLSyncKHRRef> egl_sync_ref( 1761 return;
1541 new EGLSyncKHRRef(egl_display_, egl_sync)); 1762 }
1763
1764 egl_sync_ref.reset(new EGLSyncKHRRef(egl_display_, egl_sync));
1765 }
1766
1542 decoder_thread_task_runner_->PostTask( 1767 decoder_thread_task_runner_->PostTask(
1543 FROM_HERE, 1768 FROM_HERE,
1544 base::Bind(&V4L2SliceVideoDecodeAccelerator::ReusePictureBufferTask, 1769 base::Bind(&V4L2SliceVideoDecodeAccelerator::ReusePictureBufferTask,
1545 base::Unretained(this), picture_buffer_id, 1770 base::Unretained(this), picture_buffer_id,
1546 base::Passed(&egl_sync_ref))); 1771 base::Passed(&egl_sync_ref)));
1547 } 1772 }
1548 1773
1549 void V4L2SliceVideoDecodeAccelerator::ReusePictureBufferTask( 1774 void V4L2SliceVideoDecodeAccelerator::ReusePictureBufferTask(
1550 int32_t picture_buffer_id, 1775 int32_t picture_buffer_id,
1551 std::unique_ptr<EGLSyncKHRRef> egl_sync_ref) { 1776 std::unique_ptr<EGLSyncKHRRef> egl_sync_ref) {
(...skipping 16 matching lines...) Expand all
1568 OutputRecord& output_record = output_buffer_map_[it->second->output_record()]; 1793 OutputRecord& output_record = output_buffer_map_[it->second->output_record()];
1569 if (output_record.at_device || !output_record.at_client) { 1794 if (output_record.at_device || !output_record.at_client) {
1570 DVLOGF(1) << "picture_buffer_id not reusable"; 1795 DVLOGF(1) << "picture_buffer_id not reusable";
1571 NOTIFY_ERROR(INVALID_ARGUMENT); 1796 NOTIFY_ERROR(INVALID_ARGUMENT);
1572 return; 1797 return;
1573 } 1798 }
1574 1799
1575 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); 1800 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR);
1576 DCHECK(!output_record.at_device); 1801 DCHECK(!output_record.at_device);
1577 output_record.at_client = false; 1802 output_record.at_client = false;
1578 output_record.egl_sync = egl_sync_ref->egl_sync; 1803 if (egl_sync_ref) {
1579 // Take ownership of the EGLSync. 1804 output_record.egl_sync = egl_sync_ref->egl_sync;
1580 egl_sync_ref->egl_sync = EGL_NO_SYNC_KHR; 1805 // Take ownership of the EGLSync.
1806 egl_sync_ref->egl_sync = EGL_NO_SYNC_KHR;
1807 }
1808
1581 surfaces_at_display_.erase(it); 1809 surfaces_at_display_.erase(it);
1582 } 1810 }
1583 1811
1584 void V4L2SliceVideoDecodeAccelerator::Flush() { 1812 void V4L2SliceVideoDecodeAccelerator::Flush() {
1585 DVLOGF(3); 1813 DVLOGF(3);
1586 DCHECK(child_task_runner_->BelongsToCurrentThread()); 1814 DCHECK(child_task_runner_->BelongsToCurrentThread());
1587 1815
1588 decoder_thread_task_runner_->PostTask( 1816 decoder_thread_task_runner_->PostTask(
1589 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::FlushTask, 1817 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::FlushTask,
1590 base::Unretained(this))); 1818 base::Unretained(this)));
(...skipping 13 matching lines...) Expand all
1604 } 1832 }
1605 1833
1606 // No more inputs pending, so just finish flushing here. 1834 // No more inputs pending, so just finish flushing here.
1607 InitiateFlush(); 1835 InitiateFlush();
1608 } 1836 }
1609 1837
1610 void V4L2SliceVideoDecodeAccelerator::InitiateFlush() { 1838 void V4L2SliceVideoDecodeAccelerator::InitiateFlush() {
1611 DVLOGF(3); 1839 DVLOGF(3);
1612 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 1840 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1613 1841
1614 DCHECK(!decoder_flushing_);
1615 DCHECK_EQ(state_, kDecoding);
1616 state_ = kIdle;
1617
1618 // This will trigger output for all remaining surfaces in the decoder. 1842 // This will trigger output for all remaining surfaces in the decoder.
1619 // However, not all of them may be decoded yet (they would be queued 1843 // However, not all of them may be decoded yet (they would be queued
1620 // in hardware then). 1844 // in hardware then).
1621 if (!decoder_->Flush()) { 1845 if (!decoder_->Flush()) {
1622 DVLOGF(1) << "Failed flushing the decoder."; 1846 DVLOGF(1) << "Failed flushing the decoder.";
1623 NOTIFY_ERROR(PLATFORM_FAILURE); 1847 NOTIFY_ERROR(PLATFORM_FAILURE);
1624 return; 1848 return;
1625 } 1849 }
1626 1850
1627 // Put the decoder in an idle state, ready to resume. 1851 // Put the decoder in an idle state, ready to resume.
1628 decoder_->Reset(); 1852 decoder_->Reset();
1629 1853
1854 DCHECK(!decoder_flushing_);
1630 decoder_flushing_ = true; 1855 decoder_flushing_ = true;
1631 1856 NewEventPending();
1632 decoder_thread_task_runner_->PostTask(
1633 FROM_HERE,
1634 base::Bind(&V4L2SliceVideoDecodeAccelerator::FinishFlushIfNeeded,
1635 base::Unretained(this)));
1636 } 1857 }
1637 1858
1638 void V4L2SliceVideoDecodeAccelerator::FinishFlushIfNeeded() { 1859 bool V4L2SliceVideoDecodeAccelerator::FinishFlush() {
1639 DVLOGF(3); 1860 DVLOGF(3);
1640 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 1861 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1641 1862
1642 if (!decoder_flushing_ || !surfaces_at_device_.empty()) 1863 if (!decoder_flushing_)
1643 return; 1864 return true;
1865
1866 if (!surfaces_at_device_.empty())
1867 return false;
1644 1868
1645 DCHECK_EQ(state_, kIdle); 1869 DCHECK_EQ(state_, kIdle);
1646 1870
1647 // At this point, all remaining surfaces are decoded and dequeued, and since 1871 // At this point, all remaining surfaces are decoded and dequeued, and since
1648 // we have already scheduled output for them in InitiateFlush(), their 1872 // we have already scheduled output for them in InitiateFlush(), their
1649 // respective PictureReady calls have been posted (or they have been queued on 1873 // respective PictureReady calls have been posted (or they have been queued on
1650 // pending_picture_ready_). So at this time, once we SendPictureReady(), 1874 // pending_picture_ready_). So at this time, once we SendPictureReady(),
1651 // we will have all remaining PictureReady() posted to the client and we 1875 // we will have all remaining PictureReady() posted to the client and we
1652 // can post NotifyFlushDone(). 1876 // can post NotifyFlushDone().
1653 DCHECK(decoder_display_queue_.empty()); 1877 DCHECK(decoder_display_queue_.empty());
1654 1878
1655 // Decoder should have already returned all surfaces and all surfaces are 1879 // Decoder should have already returned all surfaces and all surfaces are
1656 // out of hardware. There can be no other owners of input buffers. 1880 // out of hardware. There can be no other owners of input buffers.
1657 DCHECK_EQ(free_input_buffers_.size(), input_buffer_map_.size()); 1881 DCHECK_EQ(free_input_buffers_.size(), input_buffer_map_.size());
1658 1882
1659 SendPictureReady(); 1883 SendPictureReady();
1660 1884
1885 decoder_flushing_ = false;
1886 DVLOGF(3) << "Flush finished";
1887
1661 child_task_runner_->PostTask(FROM_HERE, 1888 child_task_runner_->PostTask(FROM_HERE,
1662 base::Bind(&Client::NotifyFlushDone, client_)); 1889 base::Bind(&Client::NotifyFlushDone, client_));
1663 1890
1664 decoder_flushing_ = false; 1891 return true;
1665
1666 DVLOGF(3) << "Flush finished";
1667 state_ = kDecoding;
1668 ScheduleDecodeBufferTaskIfNeeded();
1669 } 1892 }
1670 1893
1671 void V4L2SliceVideoDecodeAccelerator::Reset() { 1894 void V4L2SliceVideoDecodeAccelerator::Reset() {
1672 DVLOGF(3); 1895 DVLOGF(3);
1673 DCHECK(child_task_runner_->BelongsToCurrentThread()); 1896 DCHECK(child_task_runner_->BelongsToCurrentThread());
1674 1897
1675 decoder_thread_task_runner_->PostTask( 1898 decoder_thread_task_runner_->PostTask(
1676 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::ResetTask, 1899 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::ResetTask,
1677 base::Unretained(this))); 1900 base::Unretained(this)));
1678 } 1901 }
1679 1902
1680 void V4L2SliceVideoDecodeAccelerator::ResetTask() { 1903 void V4L2SliceVideoDecodeAccelerator::ResetTask() {
1681 DVLOGF(3); 1904 DVLOGF(3);
1682 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 1905 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1683 1906
1684 if (decoder_resetting_) { 1907 if (decoder_resetting_) {
1685 // This is a bug in the client, multiple Reset()s before NotifyResetDone() 1908 // This is a bug in the client, multiple Reset()s before NotifyResetDone()
1686 // are not allowed. 1909 // are not allowed.
1687 NOTREACHED() << "Client should not be requesting multiple Reset()s"; 1910 NOTREACHED() << "Client should not be requesting multiple Reset()s";
1688 return; 1911 return;
1689 } 1912 }
1690 1913
1691 DCHECK_EQ(state_, kDecoding);
1692 state_ = kIdle;
1693
1694 // Put the decoder in an idle state, ready to resume. 1914 // Put the decoder in an idle state, ready to resume.
1695 decoder_->Reset(); 1915 decoder_->Reset();
1696 1916
1697 decoder_resetting_ = true;
1698
1699 // Drop all remaining inputs. 1917 // Drop all remaining inputs.
1700 decoder_current_bitstream_buffer_.reset(); 1918 decoder_current_bitstream_buffer_.reset();
1701 while (!decoder_input_queue_.empty()) 1919 while (!decoder_input_queue_.empty())
1702 decoder_input_queue_.pop(); 1920 decoder_input_queue_.pop();
1703 1921
1704 FinishResetIfNeeded(); 1922 decoder_resetting_ = true;
1923 NewEventPending();
1705 } 1924 }
1706 1925
1707 void V4L2SliceVideoDecodeAccelerator::FinishResetIfNeeded() { 1926 bool V4L2SliceVideoDecodeAccelerator::FinishReset() {
1708 DVLOGF(3); 1927 DVLOGF(3);
1709 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); 1928 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1710 1929
1711 if (!decoder_resetting_ || !surfaces_at_device_.empty()) 1930 if (!decoder_resetting_)
1712 return; 1931 return true;
1932
1933 if (!surfaces_at_device_.empty())
1934 return false;
1713 1935
1714 DCHECK_EQ(state_, kIdle); 1936 DCHECK_EQ(state_, kIdle);
1715 DCHECK(!decoder_flushing_); 1937 DCHECK(!decoder_flushing_);
1716 SendPictureReady(); 1938 SendPictureReady();
1717 1939
1718 // Drop any pending outputs. 1940 // Drop any pending outputs.
1719 while (!decoder_display_queue_.empty()) 1941 while (!decoder_display_queue_.empty())
1720 decoder_display_queue_.pop(); 1942 decoder_display_queue_.pop();
1721 1943
1722 // At this point we can have no input buffers in the decoder, because we 1944 // At this point we can have no input buffers in the decoder, because we
1723 // Reset()ed it in ResetTask(), and have not scheduled any new Decode()s 1945 // Reset()ed it in ResetTask(), and have not scheduled any new Decode()s
1724 // having been in kIdle since. We don't have any surfaces in the HW either - 1946 // having been in kIdle since. We don't have any surfaces in the HW either -
1725 // we just checked that surfaces_at_device_.empty(), and inputs are tied 1947 // we just checked that surfaces_at_device_.empty(), and inputs are tied
1726 // to surfaces. Since there can be no other owners of input buffers, we can 1948 // to surfaces. Since there can be no other owners of input buffers, we can
1727 // simply mark them all as available. 1949 // simply mark them all as available.
1728 DCHECK_EQ(input_buffer_queued_count_, 0); 1950 DCHECK_EQ(input_buffer_queued_count_, 0);
1729 free_input_buffers_.clear(); 1951 free_input_buffers_.clear();
1730 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { 1952 for (size_t i = 0; i < input_buffer_map_.size(); ++i) {
1731 DCHECK(!input_buffer_map_[i].at_device); 1953 DCHECK(!input_buffer_map_[i].at_device);
1732 ReuseInputBuffer(i); 1954 ReuseInputBuffer(i);
1733 } 1955 }
1734 1956
1735 decoder_resetting_ = false; 1957 decoder_resetting_ = false;
1958 DVLOGF(3) << "Reset finished";
1736 1959
1737 child_task_runner_->PostTask(FROM_HERE, 1960 child_task_runner_->PostTask(FROM_HERE,
1738 base::Bind(&Client::NotifyResetDone, client_)); 1961 base::Bind(&Client::NotifyResetDone, client_));
1739 1962
1740 DVLOGF(3) << "Reset finished"; 1963 return true;
1741
1742 state_ = kDecoding;
1743 ScheduleDecodeBufferTaskIfNeeded();
1744 } 1964 }
1745 1965
1746 void V4L2SliceVideoDecodeAccelerator::SetErrorState(Error error) { 1966 void V4L2SliceVideoDecodeAccelerator::SetErrorState(Error error) {
1747 // We can touch decoder_state_ only if this is the decoder thread or the 1967 // We can touch decoder_state_ only if this is the decoder thread or the
1748 // decoder thread isn't running. 1968 // decoder thread isn't running.
1749 if (decoder_thread_.IsRunning() && 1969 if (decoder_thread_.IsRunning() &&
1750 !decoder_thread_task_runner_->BelongsToCurrentThread()) { 1970 !decoder_thread_task_runner_->BelongsToCurrentThread()) {
1751 decoder_thread_task_runner_->PostTask( 1971 decoder_thread_task_runner_->PostTask(
1752 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::SetErrorState, 1972 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::SetErrorState,
1753 base::Unretained(this), error)); 1973 base::Unretained(this), error));
(...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after
2453 OutputRecord& output_record = 2673 OutputRecord& output_record =
2454 output_buffer_map_[dec_surface->output_record()]; 2674 output_buffer_map_[dec_surface->output_record()];
2455 2675
2456 bool inserted = 2676 bool inserted =
2457 surfaces_at_display_.insert(std::make_pair(output_record.picture_id, 2677 surfaces_at_display_.insert(std::make_pair(output_record.picture_id,
2458 dec_surface)).second; 2678 dec_surface)).second;
2459 DCHECK(inserted); 2679 DCHECK(inserted);
2460 2680
2461 DCHECK(!output_record.at_client); 2681 DCHECK(!output_record.at_client);
2462 DCHECK(!output_record.at_device); 2682 DCHECK(!output_record.at_device);
2463 DCHECK_NE(output_record.egl_image, EGL_NO_IMAGE_KHR);
2464 DCHECK_NE(output_record.picture_id, -1); 2683 DCHECK_NE(output_record.picture_id, -1);
2465 output_record.at_client = true; 2684 output_record.at_client = true;
2466 2685
2467 // TODO(posciak): Use visible size from decoder here instead 2686 // TODO(posciak): Use visible size from decoder here instead
2468 // (crbug.com/402760). Passing (0, 0) results in the client using the 2687 // (crbug.com/402760). Passing (0, 0) results in the client using the
2469 // visible size extracted from the container instead. 2688 // visible size extracted from the container instead.
2470 media::Picture picture(output_record.picture_id, dec_surface->bitstream_id(), 2689 media::Picture picture(output_record.picture_id, dec_surface->bitstream_id(),
2471 gfx::Rect(0, 0), false); 2690 gfx::Rect(0, 0), false);
2472 DVLOGF(3) << dec_surface->ToString() 2691 DVLOGF(3) << dec_surface->ToString()
2473 << ", bitstream_id: " << picture.bitstream_buffer_id() 2692 << ", bitstream_id: " << picture.bitstream_buffer_id()
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
2559 } 2778 }
2560 2779
2561 bool V4L2SliceVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread( 2780 bool V4L2SliceVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
2562 const base::WeakPtr<Client>& decode_client, 2781 const base::WeakPtr<Client>& decode_client,
2563 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { 2782 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) {
2564 decode_client_ = decode_client_; 2783 decode_client_ = decode_client_;
2565 decode_task_runner_ = decode_task_runner; 2784 decode_task_runner_ = decode_task_runner;
2566 return true; 2785 return true;
2567 } 2786 }
2568 2787
2788 media::VideoPixelFormat V4L2SliceVideoDecodeAccelerator::GetOutputFormat()
2789 const {
2790 return V4L2Device::V4L2PixFmtToVideoPixelFormat(output_format_fourcc_);
2791 }
2792
2569 // static 2793 // static
2570 media::VideoDecodeAccelerator::SupportedProfiles 2794 media::VideoDecodeAccelerator::SupportedProfiles
2571 V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles() { 2795 V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles() {
2572 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); 2796 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder);
2573 if (!device) 2797 if (!device)
2574 return SupportedProfiles(); 2798 return SupportedProfiles();
2575 2799
2576 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), 2800 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_),
2577 supported_input_fourccs_); 2801 supported_input_fourccs_);
2578 } 2802 }
2579 2803
2580 } // namespace content 2804 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698