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

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

Issue 1134113002: content/common: Remove use of MessageLoopProxy and deprecated MessageLoop APIs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix CrOS build. Created 5 years, 7 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 <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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698