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

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

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

Powered by Google App Engine
This is Rietveld 408576698