OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |