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

Side by Side Diff: chrome/gpu/gpu_arc_video_encode_accelerator.cc

Issue 2892863002: ArcBridge: Add VideoEncodeAccelerator implementation. (Closed)
Patch Set: Address Kcwu's comments Created 3 years, 6 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
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/gpu/gpu_arc_video_encode_accelerator.h"
6
7 #include <utility>
8
9 #include "base/logging.h"
10 #include "base/sys_info.h"
11 #include "media/base/video_types.h"
12 #include "media/gpu/gpu_video_encode_accelerator_factory.h"
13 #include "mojo/public/cpp/bindings/strong_binding.h"
14 #include "mojo/public/cpp/bindings/type_converter.h"
15 #include "mojo/public/cpp/system/platform_handle.h"
16
17 namespace chromeos {
18 namespace arc {
19
20 GpuArcVideoEncodeAccelerator::GpuArcVideoEncodeAccelerator(
21 const gpu::GpuPreferences& gpu_preferences)
22 : gpu_preferences_(gpu_preferences) {}
23
24 GpuArcVideoEncodeAccelerator::~GpuArcVideoEncodeAccelerator() = default;
25
26 // VideoEncodeAccelerator::Client implementation.
27 void GpuArcVideoEncodeAccelerator::RequireBitstreamBuffers(
28 unsigned int input_count,
29 const gfx::Size& coded_size,
30 size_t output_buffer_size) {
31 DVLOG(2) << "RequireBitstreamBuffers(input_count=" << input_count
32 << ", coded_size=" << coded_size.ToString()
33 << ", output_buffer_size=" << output_buffer_size << ")";
34 DCHECK(client_);
35 coded_size_ = coded_size;
36 client_->RequireBitstreamBuffers(input_count, coded_size, output_buffer_size);
37 }
38
39 void GpuArcVideoEncodeAccelerator::BitstreamBufferReady(
40 int32_t bitstream_buffer_id,
41 size_t payload_size,
42 bool key_frame,
43 base::TimeDelta timestamp) {
44 DVLOG(2) << "BitstreamBufferReady(id=" << bitstream_buffer_id << ")";
45 DCHECK(client_);
46 client_->BitstreamBufferReady(bitstream_buffer_id, payload_size, key_frame,
47 timestamp.InMicroseconds());
48 }
49
50 void GpuArcVideoEncodeAccelerator::NotifyError(Error error) {
51 DVLOG(2) << "NotifyError(" << error << ")";
52 DCHECK(client_);
53 client_->NotifyError(error);
54 }
55
56 // ::arc::mojom::VideoEncodeAccelerator implementation.
57 void GpuArcVideoEncodeAccelerator::GetSupportedProfiles(
58 const GetSupportedProfilesCallback& callback) {
59 callback.Run(
60 std::move(media::GpuVideoEncodeAcceleratorFactory::GetSupportedProfiles(
Luis Héctor Chávez 2017/06/07 16:02:36 nit: this std::move() is not needed since it's not
Owen Lin 2017/06/08 04:15:47 I see. Thanks.
61 gpu_preferences_)));
62 }
63
64 void GpuArcVideoEncodeAccelerator::Initialize(
65 VideoPixelFormat input_format,
66 const gfx::Size& visible_size,
67 VideoEncodeAccelerator::StorageType input_storage,
68 VideoCodecProfile output_profile,
69 uint32_t initial_bitrate,
70 VideoEncodeClientPtr client,
71 const InitializeCallback& callback) {
72 DVLOG(2) << "Initialize()";
73
74 if (!client) {
75 DLOG(ERROR) << "Invalid client";
76 callback.Run(false);
77 return;
78 }
79
80 input_pixel_format_ = static_cast<media::VideoPixelFormat>(input_format);
81 visible_size_ = visible_size;
82 accelerator_ = media::GpuVideoEncodeAcceleratorFactory::CreateVEA(
83 input_pixel_format_, visible_size_,
84 static_cast<media::VideoCodecProfile>(output_profile), initial_bitrate,
85 this, gpu_preferences_);
86 if (accelerator_ == nullptr) {
87 DLOG(ERROR) << "failed to create vea.";
Luis Héctor Chávez 2017/06/07 16:02:36 nit: s/vea/Accelerator/, for consistency with the
Owen Lin 2017/06/08 04:15:47 Done.
88 callback.Run(false);
89 return;
90 }
91 client_ = std::move(client);
92 callback.Run(true);
93 }
94
95 static void DropSharedMemory(std::unique_ptr<base::SharedMemory> shm) {
96 // Just let |shm| fall out of scope.
97 }
98
99 void GpuArcVideoEncodeAccelerator::Encode(
100 mojo::ScopedHandle handle,
101 std::vector<::arc::VideoFramePlane> planes,
102 int64_t timestamp,
103 bool force_keyframe) {
104 DVLOG(2) << "Encode(timestamp=" << timestamp << ")";
105 if (!accelerator_) {
106 DLOG(ERROR) << "Accelerator not initialized";
107 return;
108 }
109
110 scoped_refptr<media::VideoFrame> frame;
111 if (planes.empty()) { // EOS
112 frame = media::VideoFrame::CreateEOSFrame();
Luis Héctor Chávez 2017/06/07 16:02:36 nit: use guard clause pattern: if (planes.empty(
Owen Lin 2017/06/08 04:15:46 Done.
113 } else {
114 base::ScopedFD fd = UnwrapFdFromMojoHandle(std::move(handle));
115 if (!fd.is_valid())
116 return;
117
118 size_t allocation_size =
119 media::VideoFrame::AllocationSize(input_pixel_format_, coded_size_);
120
121 // TODO(rockot): Pass GUIDs through Mojo. https://crbug.com/713763.
122 // TODO(rockot): This fd comes from a mojo::ScopedHandle in
123 // GpuArcVideoService::BindSharedMemory. That should be passed through,
124 // rather than pulling out the fd. https://crbug.com/713763.
125 // TODO(rockot): Pass through a real size rather than |0|.
126 base::UnguessableToken guid = base::UnguessableToken::Create();
127 base::SharedMemoryHandle shm_handle(
128 base::FileDescriptor(fd.release(), true), 0u, guid);
129 auto shm = base::MakeUnique<base::SharedMemory>(shm_handle, true);
130
131 base::CheckedNumeric<off_t> map_offset = planes[0].offset;
132 base::CheckedNumeric<size_t> map_size = allocation_size;
133 const uint32_t aligned_offset =
134 planes[0].offset % base::SysInfo::VMAllocationGranularity();
135 map_offset -= aligned_offset;
136 map_size += aligned_offset;
137
138 if (!map_offset.IsValid() || !map_size.IsValid()) {
139 DLOG(ERROR) << "Invalid map_offset or map_size";
140 client_->NotifyError(Error::kInvalidArgumentError);
141 return;
142 }
143 if (!shm->MapAt(map_offset.ValueOrDie(), map_size.ValueOrDie())) {
144 DLOG(ERROR) << "Could not map memroy";
Luis Héctor Chávez 2017/06/07 16:17:36 nit: s/memroy/memory/
Owen Lin 2017/06/08 04:15:47 Done.
145 client_->NotifyError(Error::kPlatformFailureError);
146 return;
147 }
148
149 uint8_t* shm_memory = reinterpret_cast<uint8_t*>(shm->memory());
150 frame = media::VideoFrame::WrapExternalSharedMemory(
151 input_pixel_format_, coded_size_, gfx::Rect(visible_size_),
152 visible_size_, shm_memory + aligned_offset, allocation_size, shm_handle,
153 planes[0].offset, base::TimeDelta::FromMicroseconds(timestamp));
154
155 // Wrap |shm| in a callback and add it as a destruction observer, so it
156 // stays alive and mapped until |frame| goes out of scope.
157 frame->AddDestructionObserver(
158 base::Bind(&DropSharedMemory, base::Passed(&shm)));
159 }
160 accelerator_->Encode(frame, force_keyframe);
161 }
162
163 void GpuArcVideoEncodeAccelerator::UseOutputBitstreamBuffer(
164 int32_t bitstream_buffer_id,
165 mojo::ScopedHandle shmem_fd,
166 uint32_t offset,
167 uint32_t size) {
168 DVLOG(2) << "UseOutputBitstreamBuffer(id=" << bitstream_buffer_id << ")";
169 if (!accelerator_) {
170 DLOG(ERROR) << "Accelerator not initialized";
171 return;
172 }
173
174 base::ScopedFD fd = UnwrapFdFromMojoHandle(std::move(shmem_fd));
175 if (!fd.is_valid())
176 return;
177
178 // TODO(rockot): Pass GUIDs through Mojo. https://crbug.com/713763.
179 // TODO(rockot): This fd comes from a mojo::ScopedHandle in
180 // GpuArcVideoService::BindSharedMemory. That should be passed through,
181 // rather than pulling out the fd. https://crbug.com/713763.
182 // TODO(rockot): Pass through a real size rather than |0|.
183 base::UnguessableToken guid = base::UnguessableToken::Create();
184 base::SharedMemoryHandle shm_handle(base::FileDescriptor(fd.release(), true),
185 0u, guid);
186 accelerator_->UseOutputBitstreamBuffer(
187 media::BitstreamBuffer(bitstream_buffer_id, shm_handle, size, offset));
188 }
189
190 void GpuArcVideoEncodeAccelerator::RequestEncodingParametersChange(
191 uint32_t bitrate,
192 uint32_t framerate) {
193 DVLOG(2) << "RequestEncodingParametersChange(" << bitrate << ", " << framerate
194 << ")";
195 if (!accelerator_) {
196 DLOG(ERROR) << "Accelerator not initialized";
197 return;
198 }
199 accelerator_->RequestEncodingParametersChange(bitrate, framerate);
200 }
201
202 base::ScopedFD GpuArcVideoEncodeAccelerator::UnwrapFdFromMojoHandle(
203 mojo::ScopedHandle handle) {
204 DCHECK(client_);
205 if (!handle.is_valid()) {
206 DLOG(ERROR) << "handle is invalid";
207 client_->NotifyError(Error::kInvalidArgumentError);
208 return base::ScopedFD();
209 }
210
211 base::PlatformFile platform_file;
212 MojoResult mojo_result =
213 mojo::UnwrapPlatformFile(std::move(handle), &platform_file);
214 if (mojo_result != MOJO_RESULT_OK) {
215 DLOG(ERROR) << "UnwrapPlatformFile failed: " << mojo_result;
216 client_->NotifyError(Error::kPlatformFailureError);
217 return base::ScopedFD();
218 }
219
220 return base::ScopedFD(platform_file);
221 }
222
223 } // namespace arc
224 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698