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

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

Issue 2892863002: ArcBridge: Add VideoEncodeAccelerator implementation. (Closed)
Patch Set: Created 3 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
(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 mojo {
18
19 // Make sure arc::mojom::VideoEncodeAccelerator::Error and
20 // media::VideoEncodeAccelerator::Error match.
21 #define CHECK_ERROR_ENUM(value) \
22 static_assert( \
23 static_cast<int>(arc::mojom::VideoEncodeAccelerator::Error::value) == \
24 media::VideoEncodeAccelerator::Error::value, \
Luis Héctor Chávez 2017/05/19 15:14:44 Why not make a typemap for this? You also get comp
Owen Lin 2017/06/03 13:32:32 Done.
25 "enum ##value mismatch")
26
27 CHECK_ERROR_ENUM(kIllegalStateError);
28 CHECK_ERROR_ENUM(kInvalidArgumentError);
29 CHECK_ERROR_ENUM(kPlatformFailureError);
30 CHECK_ERROR_ENUM(kErrorMax);
31
32 #undef CHECK_ERROR_ENUM
33
34 // Make sure values in arc::mojom::VideoPixelFormat match to the values in
35 // media::VideoPixelFormat. The former is a subset of the later.
36 #define CHECK_PIXEL_FORMAT_ENUM(value) \
37 static_assert( \
38 static_cast<int>(arc::mojom::VideoPixelFormat::value) == media::value, \
39 "enum ##value mismatch")
40
41 CHECK_PIXEL_FORMAT_ENUM(PIXEL_FORMAT_I420);
42
43 #undef CHECK_PXIEL_FORMAT_ENUM
44
45 // Make sure values in arc::mojom::VideoCodecProfile match to the values in
46 // media::VideoCodecProfile.
47 #define CHECK_PROFILE_ENUM(value) \
48 static_assert( \
49 static_cast<int>(arc::mojom::VideoCodecProfile::value) == media::value, \
50 "enum ##value mismatch")
51
52 CHECK_PROFILE_ENUM(H264PROFILE_BASELINE);
53 CHECK_PROFILE_ENUM(H264PROFILE_MAIN);
54 CHECK_PROFILE_ENUM(H264PROFILE_EXTENDED);
55 CHECK_PROFILE_ENUM(H264PROFILE_HIGH);
56 CHECK_PROFILE_ENUM(H264PROFILE_HIGH10PROFILE);
57 CHECK_PROFILE_ENUM(H264PROFILE_HIGH422PROFILE);
58 CHECK_PROFILE_ENUM(H264PROFILE_HIGH444PREDICTIVEPROFILE);
59 CHECK_PROFILE_ENUM(H264PROFILE_SCALABLEBASELINE);
60 CHECK_PROFILE_ENUM(H264PROFILE_SCALABLEHIGH);
61 CHECK_PROFILE_ENUM(H264PROFILE_STEREOHIGH);
62 CHECK_PROFILE_ENUM(H264PROFILE_MULTIVIEWHIGH);
63 CHECK_PROFILE_ENUM(VP8PROFILE_ANY);
64 CHECK_PROFILE_ENUM(VP9PROFILE_PROFILE0);
65 CHECK_PROFILE_ENUM(VP9PROFILE_PROFILE1);
66 CHECK_PROFILE_ENUM(VP9PROFILE_PROFILE2);
67 CHECK_PROFILE_ENUM(VP9PROFILE_PROFILE3);
68
69 #undef CHECK_PROFILE_ENUM
70
71 template <>
72 struct TypeConverter<arc::mojom::VideoEncodeProfilePtr,
Luis Héctor Chávez 2017/05/19 15:14:44 same here, TypeConverters are discouraged in new c
Owen Lin 2017/06/03 13:32:32 Done.
73 media::VideoEncodeAccelerator::SupportedProfile> {
74 static arc::mojom::VideoEncodeProfilePtr Convert(
75 media::VideoEncodeAccelerator::SupportedProfile input) {
76 auto result = arc::mojom::VideoEncodeProfile::New();
77 result->profile = static_cast<arc::mojom::VideoCodecProfile>(input.profile);
78 result->max_resolution = input.max_resolution;
79 result->max_framerate_numerator = input.max_framerate_numerator;
80 result->max_framerate_denominator = input.max_framerate_denominator;
81 return result;
82 }
83 };
84
85 } // namespace mojo
86
87 namespace chromeos {
88 namespace arc {
89
90 GpuArcVideoEncodeAccelerator::GpuArcVideoEncodeAccelerator(
91 const gpu::GpuPreferences& gpu_preferences)
92 : gpu_preferences_(gpu_preferences) {}
93
94 GpuArcVideoEncodeAccelerator::~GpuArcVideoEncodeAccelerator() = default;
95
96 // VideoEncodeAccelerator::Client implementation.
97 void GpuArcVideoEncodeAccelerator::RequireBitstreamBuffers(
98 unsigned int input_count,
99 const gfx::Size& input_coded_size,
100 size_t output_buffer_size) {
101 DVLOG(2) << "RequireBitstreamBuffers(input_count=" << input_count
102 << ", input_coded_size=" << input_coded_size.ToString()
103 << ", output_buffer_size=" << output_buffer_size << ")";
104 DCHECK(client_);
105 input_coded_size_ = input_coded_size;
106 client_->RequireBitstreamBuffers(input_count, input_coded_size,
107 output_buffer_size);
108 }
109
110 void GpuArcVideoEncodeAccelerator::BitstreamBufferReady(
111 int32_t bitstream_buffer_id,
112 size_t payload_size,
113 bool key_frame,
114 base::TimeDelta timestamp) {
115 DVLOG(2) << "BitstreamBufferReady(id=" << bitstream_buffer_id << ")";
116 DCHECK(client_);
117 client_->BitstreamBufferReady(bitstream_buffer_id, payload_size, key_frame,
118 timestamp.InMicroseconds());
119 }
120
121 void GpuArcVideoEncodeAccelerator::NotifyError(
122 media::VideoEncodeAccelerator::Error error) {
123 DVLOG(2) << "NotifyError(" << error << ")";
124 DCHECK(client_);
125 client_->NotifyError(static_cast<VideoEncodeAccelerator::Error>(error));
126 }
127
128 // ::arc::mojom::VideoEncodeAccelerator implementation.
129 void GpuArcVideoEncodeAccelerator::GetSupportedProfiles(
130 const GetSupportedProfilesCallback& callback) {
131 std::vector<::arc::mojom::VideoEncodeProfilePtr> profiles;
132 for (auto p : media::GpuVideoEncodeAcceleratorFactory::GetSupportedProfiles(
133 gpu_preferences_))
Luis Héctor Chávez 2017/05/19 15:14:44 nit: you cannot elide braces if the 'for' does not
Owen Lin 2017/06/03 13:32:31 Code is modified.
134 profiles.push_back(::arc::mojom::VideoEncodeProfile::From(p));
135 callback.Run(std::move(profiles));
136 }
137
138 void GpuArcVideoEncodeAccelerator::Initialize(
139 VideoPixelFormat input_format,
140 const gfx::Size& visible_size,
141 VideoEncodeAccelerator::StorageType input_storage,
142 VideoCodecProfile output_profile,
143 uint32_t initial_bitrate,
144 VideoEncodeClientPtr client,
145 const InitializeCallback& callback) {
146 DVLOG(2) << "Initialize()";
147
148 if (!::arc::mojom::IsKnownEnumValue(input_format)) {
149 DLOG(ERROR) << "Invalid input_format: " << input_format;
150 callback.Run(false);
151 return;
152 }
153 if (!::arc::mojom::IsKnownEnumValue(output_profile)) {
154 DLOG(ERROR) << "Invalid codec profile: " << output_profile;
155 callback.Run(false);
156 return;
157 }
158 if (!client) {
159 DLOG(ERROR) << "Invalid client";
160 callback.Run(false);
161 return;
162 }
163
164 input_pixel_format_ = static_cast<media::VideoPixelFormat>(input_format);
165 accelerator_ = media::GpuVideoEncodeAcceleratorFactory::CreateVEA(
166 input_pixel_format_, visible_size,
167 static_cast<media::VideoCodecProfile>(output_profile), initial_bitrate,
168 this, gpu_preferences_);
169 if (accelerator_ == nullptr) {
170 DLOG(ERROR) << "failed to create vea.";
171 callback.Run(false);
172 return;
173 }
174 client_ = std::move(client);
175 callback.Run(true);
176 }
177
178 static void DropSharedMemory(std::unique_ptr<base::SharedMemory> shm) {
179 // Just let |shm| fall out of scope.
180 }
181
182 void GpuArcVideoEncodeAccelerator::Encode(
183 mojo::ScopedHandle handle,
184 std::vector<::arc::VideoFramePlane> planes,
185 const gfx::Size& visible_size,
186 int64_t timestamp,
187 bool force_keyframe) {
188 DVLOG(2) << "Encode(timestamp=" << timestamp << ")";
189 if (!accelerator_) {
190 DLOG(ERROR) << "Accelerator not initialized";
191 return;
192 }
193
194 scoped_refptr<media::VideoFrame> frame;
195 if (planes.empty()) { // EOS
196 frame = media::VideoFrame::CreateEOSFrame();
197 } else {
198 base::ScopedFD fd = UnwrapFdFromMojoHandle(std::move(handle));
199 if (!fd.is_valid())
200 return;
201
202 size_t allocation_size = media::VideoFrame::AllocationSize(
203 input_pixel_format_, input_coded_size_);
204
205 // TODO(rockot): Pass GUIDs through Mojo. https://crbug.com/713763.
206 // TODO(rockot): This fd comes from a mojo::ScopedHandle in
207 // GpuArcVideoService::BindSharedMemory. That should be passed through,
208 // rather than pulling out the fd. https://crbug.com/713763.
209 // TODO(rockot): Pass through a real size rather than |0|.
210 base::UnguessableToken guid = base::UnguessableToken::Create();
211 base::SharedMemoryHandle shm_handle(
212 base::FileDescriptor(fd.release(), true), 0u, guid);
213 auto shm = base::MakeUnique<base::SharedMemory>(shm_handle, true);
214
215 base::CheckedNumeric<off_t> map_offset = planes[0].offset;
216 base::CheckedNumeric<size_t> map_size = allocation_size;
217 const uint32_t aligned_offset =
218 planes[0].offset % base::SysInfo::VMAllocationGranularity();
219 map_offset -= aligned_offset;
220 map_size += aligned_offset;
221
222 if (!map_offset.IsValid() || !map_size.IsValid()) {
223 DLOG(ERROR) << "Invalid map_offset or map_size";
224 client_->NotifyError(Error::kInvalidArgumentError);
225 return;
226 }
227 if (!shm->MapAt(map_offset.ValueOrDie(), map_size.ValueOrDie())) {
228 DLOG(ERROR) << "Could not map memroy";
229 client_->NotifyError(Error::kPlatformFailureError);
230 return;
231 }
232
233 uint8_t* shm_memory = reinterpret_cast<uint8_t*>(shm->memory());
234 frame = media::VideoFrame::WrapExternalSharedMemory(
235 input_pixel_format_, input_coded_size_, gfx::Rect(visible_size),
236 visible_size, shm_memory + aligned_offset, allocation_size, shm_handle,
237 planes[0].offset, base::TimeDelta::FromMicroseconds(timestamp));
238
239 // Wrap |shm| in a callback and add it as a destruction observer, so it
240 // stays alive and mapped until |frame| goes out of scope.
241 frame->AddDestructionObserver(
242 base::Bind(&DropSharedMemory, base::Passed(&shm)));
243 }
244 accelerator_->Encode(frame, force_keyframe);
245 }
246
247 void GpuArcVideoEncodeAccelerator::UseOutputBitstreamBuffer(
248 int32_t bitstream_buffer_id,
249 mojo::ScopedHandle shmem_fd,
250 uint32_t offset,
251 uint32_t size) {
252 DVLOG(2) << "UseOutputBitstreamBuffer(id=" << bitstream_buffer_id << ")";
253 if (!accelerator_) {
254 DLOG(ERROR) << "Accelerator not initialized";
255 return;
256 }
257
258 base::ScopedFD fd = UnwrapFdFromMojoHandle(std::move(shmem_fd));
259 if (!fd.is_valid())
260 return;
261
262 // TODO(rockot): Pass GUIDs through Mojo. https://crbug.com/713763.
263 // TODO(rockot): This fd comes from a mojo::ScopedHandle in
264 // GpuArcVideoService::BindSharedMemory. That should be passed through,
265 // rather than pulling out the fd. https://crbug.com/713763.
266 // TODO(rockot): Pass through a real size rather than |0|.
267 base::UnguessableToken guid = base::UnguessableToken::Create();
268 base::SharedMemoryHandle shm_handle(base::FileDescriptor(fd.release(), true),
269 0u, guid);
270 accelerator_->UseOutputBitstreamBuffer(
271 media::BitstreamBuffer(bitstream_buffer_id, shm_handle, size, offset));
272 }
273
274 void GpuArcVideoEncodeAccelerator::RequestEncodingParametersChange(
275 uint32_t bitrate,
276 uint32_t framerate) {
277 DVLOG(2) << "RequestEncodingParametersChange(" << bitrate << ", " << framerate
278 << ")";
279 if (!accelerator_) {
280 DLOG(ERROR) << "Accelerator not initialized";
281 return;
282 }
283 accelerator_->RequestEncodingParametersChange(bitrate, framerate);
284 }
285
286 base::ScopedFD GpuArcVideoEncodeAccelerator::UnwrapFdFromMojoHandle(
287 mojo::ScopedHandle handle) {
288 DCHECK(client_);
289 if (!handle.is_valid()) {
290 DLOG(ERROR) << "handle is invalid";
291 client_->NotifyError(Error::kInvalidArgumentError);
292 return base::ScopedFD();
293 }
294
295 base::PlatformFile platform_file;
296 MojoResult mojo_result =
297 mojo::UnwrapPlatformFile(std::move(handle), &platform_file);
298 if (mojo_result != MOJO_RESULT_OK) {
299 DLOG(ERROR) << "UnwrapPlatformFile failed: " << mojo_result;
300 client_->NotifyError(Error::kPlatformFailureError);
301 return base::ScopedFD();
302 }
303
304 return base::ScopedFD(platform_file);
305 }
306
307 } // namespace arc
308 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698