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

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

Issue 2398883002: Add support for multiple V4L2 video devices of the same type. (Closed)
Patch Set: Address comments, reorganize V4L2Device::Type. Created 4 years, 2 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 "media/gpu/v4l2_slice_video_decode_accelerator.h" 5 #include "media/gpu/v4l2_slice_video_decode_accelerator.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <linux/videodev2.h> 9 #include <linux/videodev2.h>
10 #include <poll.h> 10 #include <poll.h>
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 output_planes_count_(0), 465 output_planes_count_(0),
466 child_task_runner_(base::ThreadTaskRunnerHandle::Get()), 466 child_task_runner_(base::ThreadTaskRunnerHandle::Get()),
467 device_(device), 467 device_(device),
468 decoder_thread_("V4L2SliceVideoDecodeAcceleratorThread"), 468 decoder_thread_("V4L2SliceVideoDecodeAcceleratorThread"),
469 device_poll_thread_("V4L2SliceVideoDecodeAcceleratorDevicePollThread"), 469 device_poll_thread_("V4L2SliceVideoDecodeAcceleratorDevicePollThread"),
470 input_streamon_(false), 470 input_streamon_(false),
471 input_buffer_queued_count_(0), 471 input_buffer_queued_count_(0),
472 output_streamon_(false), 472 output_streamon_(false),
473 output_buffer_queued_count_(0), 473 output_buffer_queued_count_(0),
474 video_profile_(VIDEO_CODEC_PROFILE_UNKNOWN), 474 video_profile_(VIDEO_CODEC_PROFILE_UNKNOWN),
475 input_format_fourcc_(0),
475 output_format_fourcc_(0), 476 output_format_fourcc_(0),
476 state_(kUninitialized), 477 state_(kUninitialized),
477 output_mode_(Config::OutputMode::ALLOCATE), 478 output_mode_(Config::OutputMode::ALLOCATE),
478 decoder_flushing_(false), 479 decoder_flushing_(false),
479 decoder_resetting_(false), 480 decoder_resetting_(false),
480 surface_set_change_pending_(false), 481 surface_set_change_pending_(false),
481 picture_clearing_count_(0), 482 picture_clearing_count_(0),
482 egl_display_(egl_display), 483 egl_display_(egl_display),
483 get_gl_context_cb_(get_gl_context_cb), 484 get_gl_context_cb_(get_gl_context_cb),
484 make_context_current_cb_(make_context_current_cb), 485 make_context_current_cb_(make_context_current_cb),
(...skipping 25 matching lines...) Expand all
510 client_ptr_factory_.reset(); 511 client_ptr_factory_.reset();
511 } 512 }
512 } 513 }
513 514
514 bool V4L2SliceVideoDecodeAccelerator::Initialize(const Config& config, 515 bool V4L2SliceVideoDecodeAccelerator::Initialize(const Config& config,
515 Client* client) { 516 Client* client) {
516 DVLOGF(3) << "profile: " << config.profile; 517 DVLOGF(3) << "profile: " << config.profile;
517 DCHECK(child_task_runner_->BelongsToCurrentThread()); 518 DCHECK(child_task_runner_->BelongsToCurrentThread());
518 DCHECK_EQ(state_, kUninitialized); 519 DCHECK_EQ(state_, kUninitialized);
519 520
520 if (!device_->SupportsDecodeProfileForV4L2PixelFormats(
521 config.profile, arraysize(supported_input_fourccs_),
522 supported_input_fourccs_)) {
523 DVLOGF(1) << "unsupported profile " << config.profile;
524 return false;
525 }
526
527 if (config.is_encrypted) { 521 if (config.is_encrypted) {
528 NOTREACHED() << "Encrypted streams are not supported for this VDA"; 522 NOTREACHED() << "Encrypted streams are not supported for this VDA";
529 return false; 523 return false;
530 } 524 }
531 525
532 if (config.output_mode != Config::OutputMode::ALLOCATE && 526 if (config.output_mode != Config::OutputMode::ALLOCATE &&
533 config.output_mode != Config::OutputMode::IMPORT) { 527 config.output_mode != Config::OutputMode::IMPORT) {
534 NOTREACHED() << "Only ALLOCATE and IMPORT OutputModes are supported"; 528 NOTREACHED() << "Only ALLOCATE and IMPORT OutputModes are supported";
535 return false; 529 return false;
536 } 530 }
537 531
538 client_ptr_factory_.reset( 532 client_ptr_factory_.reset(
539 new base::WeakPtrFactory<VideoDecodeAccelerator::Client>(client)); 533 new base::WeakPtrFactory<VideoDecodeAccelerator::Client>(client));
540 client_ = client_ptr_factory_->GetWeakPtr(); 534 client_ = client_ptr_factory_->GetWeakPtr();
541 // If we haven't been set up to decode on separate thread via 535 // If we haven't been set up to decode on separate thread via
542 // TryToSetupDecodeOnSeparateThread(), use the main thread/client for 536 // TryToSetupDecodeOnSeparateThread(), use the main thread/client for
543 // decode tasks. 537 // decode tasks.
544 if (!decode_task_runner_) { 538 if (!decode_task_runner_) {
545 decode_task_runner_ = child_task_runner_; 539 decode_task_runner_ = child_task_runner_;
546 DCHECK(!decode_client_); 540 DCHECK(!decode_client_);
547 decode_client_ = client_; 541 decode_client_ = client_;
548 } 542 }
549 543
550 video_profile_ = config.profile;
551
552 if (video_profile_ >= H264PROFILE_MIN && video_profile_ <= H264PROFILE_MAX) {
553 h264_accelerator_.reset(new V4L2H264Accelerator(this));
554 decoder_.reset(new H264Decoder(h264_accelerator_.get()));
555 } else if (video_profile_ >= VP8PROFILE_MIN &&
556 video_profile_ <= VP8PROFILE_MAX) {
557 vp8_accelerator_.reset(new V4L2VP8Accelerator(this));
558 decoder_.reset(new VP8Decoder(vp8_accelerator_.get()));
559 } else if (video_profile_ >= VP9PROFILE_MIN &&
560 video_profile_ <= VP9PROFILE_MAX) {
561 vp9_accelerator_.reset(new V4L2VP9Accelerator(this));
562 decoder_.reset(new VP9Decoder(vp9_accelerator_.get()));
563 } else {
564 NOTREACHED() << "Unsupported profile " << video_profile_;
565 return false;
566 }
567
568 // TODO(posciak): This needs to be queried once supported.
569 input_planes_count_ = 1;
570 output_planes_count_ = 1;
571
572 if (egl_display_ == EGL_NO_DISPLAY) { 544 if (egl_display_ == EGL_NO_DISPLAY) {
573 LOGF(ERROR) << "could not get EGLDisplay"; 545 LOGF(ERROR) << "could not get EGLDisplay";
574 return false; 546 return false;
575 } 547 }
576 548
577 // We need the context to be initialized to query extensions. 549 // We need the context to be initialized to query extensions.
578 if (!make_context_current_cb_.is_null()) { 550 if (!make_context_current_cb_.is_null()) {
579 if (!make_context_current_cb_.Run()) { 551 if (!make_context_current_cb_.Run()) {
580 LOGF(ERROR) << "could not make context current"; 552 LOGF(ERROR) << "could not make context current";
581 return false; 553 return false;
582 } 554 }
583 555
584 if (!gl::g_driver_egl.ext.b_EGL_KHR_fence_sync) { 556 if (!gl::g_driver_egl.ext.b_EGL_KHR_fence_sync) {
585 LOGF(ERROR) << "context does not have EGL_KHR_fence_sync"; 557 LOGF(ERROR) << "context does not have EGL_KHR_fence_sync";
586 return false; 558 return false;
587 } 559 }
588 } else { 560 } else {
589 DVLOGF(1) << "No GL callbacks provided, initializing without GL support"; 561 DVLOGF(1) << "No GL callbacks provided, initializing without GL support";
590 } 562 }
591 563
564 video_profile_ = config.profile;
565
566 // TODO(posciak): This needs to be queried once supported.
567 input_planes_count_ = 1;
568 output_planes_count_ = 1;
569
570 input_format_fourcc_ =
571 V4L2Device::VideoCodecProfileToV4L2PixFmt(video_profile_, true);
572
573 if (!device_->Open(V4L2Device::Type::kDecoder, input_format_fourcc_)) {
574 DVLOGF(1) << "Failed to open device for profile: " << config.profile
575 << " fourcc: " << std::hex << input_format_fourcc_;
kcwu 2016/10/07 11:19:05 0x
Pawel Osciak 2016/10/11 06:13:46 Done.
576 return false;
577 }
578
579 if (video_profile_ >= H264PROFILE_MIN && video_profile_ <= H264PROFILE_MAX) {
580 h264_accelerator_.reset(new V4L2H264Accelerator(this));
581 decoder_.reset(new H264Decoder(h264_accelerator_.get()));
582 } else if (video_profile_ >= VP8PROFILE_MIN &&
583 video_profile_ <= VP8PROFILE_MAX) {
584 vp8_accelerator_.reset(new V4L2VP8Accelerator(this));
585 decoder_.reset(new VP8Decoder(vp8_accelerator_.get()));
586 } else if (video_profile_ >= VP9PROFILE_MIN &&
587 video_profile_ <= VP9PROFILE_MAX) {
588 vp9_accelerator_.reset(new V4L2VP9Accelerator(this));
589 decoder_.reset(new VP9Decoder(vp9_accelerator_.get()));
590 } else {
591 NOTREACHED() << "Unsupported profile " << video_profile_;
592 return false;
593 }
594
592 // Capabilities check. 595 // Capabilities check.
593 struct v4l2_capability caps; 596 struct v4l2_capability caps;
594 const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; 597 const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
595 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps); 598 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps);
596 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { 599 if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
597 LOGF(ERROR) << "ioctl() failed: VIDIOC_QUERYCAP" 600 LOGF(ERROR) << "ioctl() failed: VIDIOC_QUERYCAP"
598 << ", caps check failed: 0x" << std::hex << caps.capabilities; 601 << ", caps check failed: 0x" << std::hex << caps.capabilities;
599 return false; 602 return false;
600 } 603 }
601 604
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
669 DestroyOutputs(false); 672 DestroyOutputs(false);
670 673
671 DCHECK(surfaces_at_device_.empty()); 674 DCHECK(surfaces_at_device_.empty());
672 DCHECK(surfaces_at_display_.empty()); 675 DCHECK(surfaces_at_display_.empty());
673 DCHECK(decoder_display_queue_.empty()); 676 DCHECK(decoder_display_queue_.empty());
674 } 677 }
675 678
676 bool V4L2SliceVideoDecodeAccelerator::SetupFormats() { 679 bool V4L2SliceVideoDecodeAccelerator::SetupFormats() {
677 DCHECK_EQ(state_, kUninitialized); 680 DCHECK_EQ(state_, kUninitialized);
678 681
679 __u32 input_format_fourcc =
680 V4L2Device::VideoCodecProfileToV4L2PixFmt(video_profile_, true);
681 if (!input_format_fourcc) {
682 NOTREACHED();
683 return false;
684 }
685
686 size_t input_size; 682 size_t input_size;
687 gfx::Size max_resolution, min_resolution; 683 gfx::Size max_resolution, min_resolution;
688 device_->GetSupportedResolution(input_format_fourcc, &min_resolution, 684 device_->GetSupportedResolution(input_format_fourcc_, &min_resolution,
689 &max_resolution); 685 &max_resolution);
690 if (max_resolution.width() > 1920 && max_resolution.height() > 1088) 686 if (max_resolution.width() > 1920 && max_resolution.height() > 1088)
691 input_size = kInputBufferMaxSizeFor4k; 687 input_size = kInputBufferMaxSizeFor4k;
692 else 688 else
693 input_size = kInputBufferMaxSizeFor1080p; 689 input_size = kInputBufferMaxSizeFor1080p;
694 690
695 struct v4l2_fmtdesc fmtdesc; 691 struct v4l2_fmtdesc fmtdesc;
696 memset(&fmtdesc, 0, sizeof(fmtdesc)); 692 memset(&fmtdesc, 0, sizeof(fmtdesc));
697 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 693 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
698 bool is_format_supported = false; 694 bool is_format_supported = false;
699 while (device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0) { 695 while (device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
700 if (fmtdesc.pixelformat == input_format_fourcc) { 696 if (fmtdesc.pixelformat == input_format_fourcc_) {
701 is_format_supported = true; 697 is_format_supported = true;
702 break; 698 break;
703 } 699 }
704 ++fmtdesc.index; 700 ++fmtdesc.index;
705 } 701 }
706 702
707 if (!is_format_supported) { 703 if (!is_format_supported) {
708 DVLOGF(1) << "Input fourcc " << input_format_fourcc 704 DVLOGF(1) << "Input fourcc " << input_format_fourcc_
709 << " not supported by device."; 705 << " not supported by device.";
710 return false; 706 return false;
711 } 707 }
712 708
713 struct v4l2_format format; 709 struct v4l2_format format;
714 memset(&format, 0, sizeof(format)); 710 memset(&format, 0, sizeof(format));
715 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 711 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
716 format.fmt.pix_mp.pixelformat = input_format_fourcc; 712 format.fmt.pix_mp.pixelformat = input_format_fourcc_;
717 format.fmt.pix_mp.plane_fmt[0].sizeimage = input_size; 713 format.fmt.pix_mp.plane_fmt[0].sizeimage = input_size;
718 format.fmt.pix_mp.num_planes = input_planes_count_; 714 format.fmt.pix_mp.num_planes = input_planes_count_;
719 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format); 715 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
720 716
721 // We have to set up the format for output, because the driver may not allow 717 // We have to set up the format for output, because the driver may not allow
722 // changing it once we start streaming; whether it can support our chosen 718 // changing it once we start streaming; whether it can support our chosen
723 // output format or not may depend on the input format. 719 // output format or not may depend on the input format.
724 memset(&fmtdesc, 0, sizeof(fmtdesc)); 720 memset(&fmtdesc, 0, sizeof(fmtdesc));
725 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 721 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
726 output_format_fourcc_ = 0; 722 output_format_fourcc_ = 0;
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
862 state_ = kAwaitingPictureBuffers; 858 state_ = kAwaitingPictureBuffers;
863 return true; 859 return true;
864 } 860 }
865 861
866 void V4L2SliceVideoDecodeAccelerator::DestroyInputBuffers() { 862 void V4L2SliceVideoDecodeAccelerator::DestroyInputBuffers() {
867 DVLOGF(3); 863 DVLOGF(3);
868 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread() || 864 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread() ||
869 !decoder_thread_.IsRunning()); 865 !decoder_thread_.IsRunning());
870 DCHECK(!input_streamon_); 866 DCHECK(!input_streamon_);
871 867
868 if (input_buffer_map_.empty())
869 return;
870
872 for (auto& input_record : input_buffer_map_) { 871 for (auto& input_record : input_buffer_map_) {
873 if (input_record.address != nullptr) 872 if (input_record.address != nullptr)
874 device_->Munmap(input_record.address, input_record.length); 873 device_->Munmap(input_record.address, input_record.length);
875 } 874 }
876 875
877 struct v4l2_requestbuffers reqbufs; 876 struct v4l2_requestbuffers reqbufs;
878 memset(&reqbufs, 0, sizeof(reqbufs)); 877 memset(&reqbufs, 0, sizeof(reqbufs));
879 reqbufs.count = 0; 878 reqbufs.count = 0;
880 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 879 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
881 reqbufs.memory = V4L2_MEMORY_MMAP; 880 reqbufs.memory = V4L2_MEMORY_MMAP;
(...skipping 2381 matching lines...) Expand 10 before | Expand all | Expand 10 after
3263 const base::WeakPtr<Client>& decode_client, 3262 const base::WeakPtr<Client>& decode_client,
3264 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { 3263 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) {
3265 decode_client_ = decode_client; 3264 decode_client_ = decode_client;
3266 decode_task_runner_ = decode_task_runner; 3265 decode_task_runner_ = decode_task_runner;
3267 return true; 3266 return true;
3268 } 3267 }
3269 3268
3270 // static 3269 // static
3271 VideoDecodeAccelerator::SupportedProfiles 3270 VideoDecodeAccelerator::SupportedProfiles
3272 V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles() { 3271 V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles() {
3273 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); 3272 scoped_refptr<V4L2Device> device = V4L2Device::Create();
3274 if (!device) 3273 if (!device)
3275 return SupportedProfiles(); 3274 return SupportedProfiles();
3276 3275
3277 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), 3276 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_),
3278 supported_input_fourccs_); 3277 supported_input_fourccs_);
3279 } 3278 }
3280 3279
3281 } // namespace media 3280 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698