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 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 | 82 |
83 // Mark the surface as decoded. This will also release all references, as | 83 // Mark the surface as decoded. This will also release all references, as |
84 // they are not needed anymore and execute the done callback, if not null. | 84 // they are not needed anymore and execute the done callback, if not null. |
85 void SetDecoded(); | 85 void SetDecoded(); |
86 bool decoded() const { return decoded_; } | 86 bool decoded() const { return decoded_; } |
87 | 87 |
88 int32_t bitstream_id() const { return bitstream_id_; } | 88 int32_t bitstream_id() const { return bitstream_id_; } |
89 int input_record() const { return input_record_; } | 89 int input_record() const { return input_record_; } |
90 int output_record() const { return output_record_; } | 90 int output_record() const { return output_record_; } |
91 uint32_t config_store() const { return config_store_; } | 91 uint32_t config_store() const { return config_store_; } |
| 92 gfx::Rect visible_rect() const { return visible_rect_; } |
| 93 |
| 94 void set_visible_rect(const gfx::Rect& visible_rect) { |
| 95 visible_rect_ = visible_rect; |
| 96 } |
92 | 97 |
93 // Take references to each reference surface and keep them until the | 98 // Take references to each reference surface and keep them until the |
94 // target surface is decoded. | 99 // target surface is decoded. |
95 void SetReferenceSurfaces( | 100 void SetReferenceSurfaces( |
96 const std::vector<scoped_refptr<V4L2DecodeSurface>>& ref_surfaces); | 101 const std::vector<scoped_refptr<V4L2DecodeSurface>>& ref_surfaces); |
97 | 102 |
98 // If provided via this method, |done_cb| callback will be executed after | 103 // If provided via this method, |done_cb| callback will be executed after |
99 // decoding into this surface is finished. The callback is reset afterwards, | 104 // decoding into this surface is finished. The callback is reset afterwards, |
100 // so it needs to be set again before each decode operation. | 105 // so it needs to be set again before each decode operation. |
101 void SetDecodeDoneCallback(const base::Closure& done_cb) { | 106 void SetDecodeDoneCallback(const base::Closure& done_cb) { |
102 DCHECK(done_cb_.is_null()); | 107 DCHECK(done_cb_.is_null()); |
103 done_cb_ = done_cb; | 108 done_cb_ = done_cb; |
104 } | 109 } |
105 | 110 |
106 std::string ToString() const; | 111 std::string ToString() const; |
107 | 112 |
108 private: | 113 private: |
109 friend class base::RefCounted<V4L2DecodeSurface>; | 114 friend class base::RefCounted<V4L2DecodeSurface>; |
110 ~V4L2DecodeSurface(); | 115 ~V4L2DecodeSurface(); |
111 | 116 |
112 int32_t bitstream_id_; | 117 int32_t bitstream_id_; |
113 int input_record_; | 118 int input_record_; |
114 int output_record_; | 119 int output_record_; |
115 uint32_t config_store_; | 120 uint32_t config_store_; |
| 121 gfx::Rect visible_rect_; |
116 | 122 |
117 bool decoded_; | 123 bool decoded_; |
118 ReleaseCB release_cb_; | 124 ReleaseCB release_cb_; |
119 base::Closure done_cb_; | 125 base::Closure done_cb_; |
120 | 126 |
121 std::vector<scoped_refptr<V4L2DecodeSurface>> reference_surfaces_; | 127 std::vector<scoped_refptr<V4L2DecodeSurface>> reference_surfaces_; |
122 | 128 |
123 DISALLOW_COPY_AND_ASSIGN(V4L2DecodeSurface); | 129 DISALLOW_COPY_AND_ASSIGN(V4L2DecodeSurface); |
124 }; | 130 }; |
125 | 131 |
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
793 } | 799 } |
794 | 800 |
795 bool V4L2SliceVideoDecodeAccelerator::CreateOutputBuffers() { | 801 bool V4L2SliceVideoDecodeAccelerator::CreateOutputBuffers() { |
796 DVLOGF(3); | 802 DVLOGF(3); |
797 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 803 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
798 DCHECK(!output_streamon_); | 804 DCHECK(!output_streamon_); |
799 DCHECK(output_buffer_map_.empty()); | 805 DCHECK(output_buffer_map_.empty()); |
800 DCHECK(surfaces_at_display_.empty()); | 806 DCHECK(surfaces_at_display_.empty()); |
801 DCHECK(surfaces_at_device_.empty()); | 807 DCHECK(surfaces_at_device_.empty()); |
802 | 808 |
803 visible_size_ = decoder_->GetPicSize(); | 809 gfx::Size pic_size = decoder_->GetPicSize(); |
804 size_t num_pictures = decoder_->GetRequiredNumOfPictures(); | 810 size_t num_pictures = decoder_->GetRequiredNumOfPictures(); |
805 | 811 |
806 DCHECK_GT(num_pictures, 0u); | 812 DCHECK_GT(num_pictures, 0u); |
807 DCHECK(!visible_size_.IsEmpty()); | 813 DCHECK(!pic_size.IsEmpty()); |
808 | 814 |
809 struct v4l2_format format; | 815 struct v4l2_format format; |
810 memset(&format, 0, sizeof(format)); | 816 memset(&format, 0, sizeof(format)); |
811 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 817 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
812 format.fmt.pix_mp.pixelformat = output_format_fourcc_; | 818 format.fmt.pix_mp.pixelformat = output_format_fourcc_; |
813 format.fmt.pix_mp.width = visible_size_.width(); | 819 format.fmt.pix_mp.width = pic_size.width(); |
814 format.fmt.pix_mp.height = visible_size_.height(); | 820 format.fmt.pix_mp.height = pic_size.height(); |
815 format.fmt.pix_mp.num_planes = input_planes_count_; | 821 format.fmt.pix_mp.num_planes = input_planes_count_; |
816 | 822 |
817 if (device_->Ioctl(VIDIOC_S_FMT, &format) != 0) { | 823 if (device_->Ioctl(VIDIOC_S_FMT, &format) != 0) { |
818 PLOGF(ERROR) << "Failed setting format to: " << output_format_fourcc_; | 824 PLOGF(ERROR) << "Failed setting format to: " << output_format_fourcc_; |
819 NOTIFY_ERROR(PLATFORM_FAILURE); | 825 NOTIFY_ERROR(PLATFORM_FAILURE); |
820 return false; | 826 return false; |
821 } | 827 } |
822 | 828 |
823 coded_size_.SetSize(base::checked_cast<int>(format.fmt.pix_mp.width), | 829 coded_size_.SetSize(base::checked_cast<int>(format.fmt.pix_mp.width), |
824 base::checked_cast<int>(format.fmt.pix_mp.height)); | 830 base::checked_cast<int>(format.fmt.pix_mp.height)); |
825 DCHECK_EQ(coded_size_.width() % 16, 0); | 831 DCHECK_EQ(coded_size_.width() % 16, 0); |
826 DCHECK_EQ(coded_size_.height() % 16, 0); | 832 DCHECK_EQ(coded_size_.height() % 16, 0); |
827 | 833 |
828 if (!gfx::Rect(coded_size_).Contains(gfx::Rect(visible_size_))) { | 834 if (!gfx::Rect(coded_size_).Contains(gfx::Rect(pic_size))) { |
829 LOGF(ERROR) << "Got invalid adjusted coded size: " | 835 LOGF(ERROR) << "Got invalid adjusted coded size: " |
830 << coded_size_.ToString(); | 836 << coded_size_.ToString(); |
831 return false; | 837 return false; |
832 } | 838 } |
833 | 839 |
834 DVLOGF(3) << "buffer_count=" << num_pictures | 840 DVLOGF(3) << "buffer_count=" << num_pictures |
835 << ", visible size=" << visible_size_.ToString() | 841 << ", pic size=" << pic_size.ToString() |
836 << ", coded size=" << coded_size_.ToString(); | 842 << ", coded size=" << coded_size_.ToString(); |
837 | 843 |
838 // With ALLOCATE mode the client can sample it as RGB and doesn't need to | 844 // With ALLOCATE mode the client can sample it as RGB and doesn't need to |
839 // know the precise format. | 845 // know the precise format. |
840 VideoPixelFormat pixel_format = | 846 VideoPixelFormat pixel_format = |
841 (output_mode_ == Config::OutputMode::IMPORT) | 847 (output_mode_ == Config::OutputMode::IMPORT) |
842 ? V4L2Device::V4L2PixFmtToVideoPixelFormat(output_format_fourcc_) | 848 ? V4L2Device::V4L2PixFmtToVideoPixelFormat(output_format_fourcc_) |
843 : PIXEL_FORMAT_UNKNOWN; | 849 : PIXEL_FORMAT_UNKNOWN; |
844 | 850 |
845 child_task_runner_->PostTask( | 851 child_task_runner_->PostTask( |
(...skipping 1676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2522 Reset(); | 2528 Reset(); |
2523 | 2529 |
2524 v4l2_dec_->DecodeSurface(dec_surface); | 2530 v4l2_dec_->DecodeSurface(dec_surface); |
2525 return true; | 2531 return true; |
2526 } | 2532 } |
2527 | 2533 |
2528 bool V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::OutputPicture( | 2534 bool V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::OutputPicture( |
2529 const scoped_refptr<H264Picture>& pic) { | 2535 const scoped_refptr<H264Picture>& pic) { |
2530 scoped_refptr<V4L2DecodeSurface> dec_surface = | 2536 scoped_refptr<V4L2DecodeSurface> dec_surface = |
2531 H264PictureToV4L2DecodeSurface(pic); | 2537 H264PictureToV4L2DecodeSurface(pic); |
| 2538 dec_surface->set_visible_rect(pic->visible_rect); |
2532 v4l2_dec_->SurfaceReady(dec_surface); | 2539 v4l2_dec_->SurfaceReady(dec_surface); |
2533 return true; | 2540 return true; |
2534 } | 2541 } |
2535 | 2542 |
2536 void V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::Reset() { | 2543 void V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::Reset() { |
2537 num_slices_ = 0; | 2544 num_slices_ = 0; |
2538 memset(&v4l2_decode_param_, 0, sizeof(v4l2_decode_param_)); | 2545 memset(&v4l2_decode_param_, 0, sizeof(v4l2_decode_param_)); |
2539 memset(&v4l2_slice_params_, 0, sizeof(v4l2_slice_params_)); | 2546 memset(&v4l2_slice_params_, 0, sizeof(v4l2_slice_params_)); |
2540 } | 2547 } |
2541 | 2548 |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2753 return false; | 2760 return false; |
2754 | 2761 |
2755 v4l2_dec_->DecodeSurface(dec_surface); | 2762 v4l2_dec_->DecodeSurface(dec_surface); |
2756 return true; | 2763 return true; |
2757 } | 2764 } |
2758 | 2765 |
2759 bool V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator::OutputPicture( | 2766 bool V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator::OutputPicture( |
2760 const scoped_refptr<VP8Picture>& pic) { | 2767 const scoped_refptr<VP8Picture>& pic) { |
2761 scoped_refptr<V4L2DecodeSurface> dec_surface = | 2768 scoped_refptr<V4L2DecodeSurface> dec_surface = |
2762 VP8PictureToV4L2DecodeSurface(pic); | 2769 VP8PictureToV4L2DecodeSurface(pic); |
2763 | 2770 dec_surface->set_visible_rect(pic->visible_rect); |
2764 v4l2_dec_->SurfaceReady(dec_surface); | 2771 v4l2_dec_->SurfaceReady(dec_surface); |
2765 return true; | 2772 return true; |
2766 } | 2773 } |
2767 | 2774 |
2768 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> | 2775 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> |
2769 V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator:: | 2776 V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator:: |
2770 VP8PictureToV4L2DecodeSurface(const scoped_refptr<VP8Picture>& pic) { | 2777 VP8PictureToV4L2DecodeSurface(const scoped_refptr<VP8Picture>& pic) { |
2771 V4L2VP8Picture* v4l2_pic = pic->AsV4L2VP8Picture(); | 2778 V4L2VP8Picture* v4l2_pic = pic->AsV4L2VP8Picture(); |
2772 CHECK(v4l2_pic); | 2779 CHECK(v4l2_pic); |
2773 return v4l2_pic->dec_surface(); | 2780 return v4l2_pic->dec_surface(); |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3056 return false; | 3063 return false; |
3057 | 3064 |
3058 v4l2_dec_->DecodeSurface(dec_surface); | 3065 v4l2_dec_->DecodeSurface(dec_surface); |
3059 return true; | 3066 return true; |
3060 } | 3067 } |
3061 | 3068 |
3062 bool V4L2SliceVideoDecodeAccelerator::V4L2VP9Accelerator::OutputPicture( | 3069 bool V4L2SliceVideoDecodeAccelerator::V4L2VP9Accelerator::OutputPicture( |
3063 const scoped_refptr<VP9Picture>& pic) { | 3070 const scoped_refptr<VP9Picture>& pic) { |
3064 scoped_refptr<V4L2DecodeSurface> dec_surface = | 3071 scoped_refptr<V4L2DecodeSurface> dec_surface = |
3065 VP9PictureToV4L2DecodeSurface(pic); | 3072 VP9PictureToV4L2DecodeSurface(pic); |
3066 | 3073 dec_surface->set_visible_rect(pic->visible_rect); |
3067 v4l2_dec_->SurfaceReady(dec_surface); | 3074 v4l2_dec_->SurfaceReady(dec_surface); |
3068 return true; | 3075 return true; |
3069 } | 3076 } |
3070 | 3077 |
3071 static void FillVp9FrameContext(struct v4l2_vp9_entropy_ctx& v4l2_entropy_ctx, | 3078 static void FillVp9FrameContext(struct v4l2_vp9_entropy_ctx& v4l2_entropy_ctx, |
3072 Vp9FrameContext* vp9_frame_ctx) { | 3079 Vp9FrameContext* vp9_frame_ctx) { |
3073 #define ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(a) \ | 3080 #define ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(a) \ |
3074 ARRAY_MEMCPY_CHECKED(vp9_frame_ctx->a, v4l2_entropy_ctx.a) | 3081 ARRAY_MEMCPY_CHECKED(vp9_frame_ctx->a, v4l2_entropy_ctx.a) |
3075 ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(tx_probs_8x8); | 3082 ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(tx_probs_8x8); |
3076 ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(tx_probs_16x16); | 3083 ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(tx_probs_16x16); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3180 surfaces_at_display_ | 3187 surfaces_at_display_ |
3181 .insert(std::make_pair(output_record.picture_id, dec_surface)) | 3188 .insert(std::make_pair(output_record.picture_id, dec_surface)) |
3182 .second; | 3189 .second; |
3183 DCHECK(inserted); | 3190 DCHECK(inserted); |
3184 | 3191 |
3185 DCHECK(!output_record.at_client); | 3192 DCHECK(!output_record.at_client); |
3186 DCHECK(!output_record.at_device); | 3193 DCHECK(!output_record.at_device); |
3187 DCHECK_NE(output_record.picture_id, -1); | 3194 DCHECK_NE(output_record.picture_id, -1); |
3188 output_record.at_client = true; | 3195 output_record.at_client = true; |
3189 | 3196 |
3190 // TODO(posciak): Use visible size from decoder here instead | |
3191 // (crbug.com/402760). Passing (0, 0) results in the client using the | |
3192 // visible size extracted from the container instead. | |
3193 // TODO(hubbe): Insert correct color space. http://crbug.com/647725 | 3197 // TODO(hubbe): Insert correct color space. http://crbug.com/647725 |
3194 Picture picture(output_record.picture_id, dec_surface->bitstream_id(), | 3198 Picture picture(output_record.picture_id, dec_surface->bitstream_id(), |
3195 gfx::Rect(0, 0), gfx::ColorSpace(), false); | 3199 dec_surface->visible_rect(), gfx::ColorSpace(), false); |
3196 DVLOGF(3) << dec_surface->ToString() | 3200 DVLOGF(3) << dec_surface->ToString() |
3197 << ", bitstream_id: " << picture.bitstream_buffer_id() | 3201 << ", bitstream_id: " << picture.bitstream_buffer_id() |
3198 << ", picture_id: " << picture.picture_buffer_id(); | 3202 << ", picture_id: " << picture.picture_buffer_id() |
| 3203 << ", visible_rect: " << picture.visible_rect().ToString(); |
3199 pending_picture_ready_.push(PictureRecord(output_record.cleared, picture)); | 3204 pending_picture_ready_.push(PictureRecord(output_record.cleared, picture)); |
3200 SendPictureReady(); | 3205 SendPictureReady(); |
3201 output_record.cleared = true; | 3206 output_record.cleared = true; |
3202 } | 3207 } |
3203 | 3208 |
3204 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> | 3209 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> |
3205 V4L2SliceVideoDecodeAccelerator::CreateSurface() { | 3210 V4L2SliceVideoDecodeAccelerator::CreateSurface() { |
3206 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 3211 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
3207 DCHECK_EQ(state_, kDecoding); | 3212 DCHECK_EQ(state_, kDecoding); |
3208 | 3213 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3295 V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles() { | 3300 V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles() { |
3296 scoped_refptr<V4L2Device> device = V4L2Device::Create(); | 3301 scoped_refptr<V4L2Device> device = V4L2Device::Create(); |
3297 if (!device) | 3302 if (!device) |
3298 return SupportedProfiles(); | 3303 return SupportedProfiles(); |
3299 | 3304 |
3300 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), | 3305 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), |
3301 supported_input_fourccs_); | 3306 supported_input_fourccs_); |
3302 } | 3307 } |
3303 | 3308 |
3304 } // namespace media | 3309 } // namespace media |
OLD | NEW |