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

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

Issue 1549473002: Add ArcGpuVideoDecodeAccelerator. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: add OWNERS file Created 4 years, 9 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
« no previous file with comments | « chrome/gpu/arc_gpu_video_decode_accelerator.h ('k') | chrome/gpu/arc_video_accelerator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 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 "base/callback_helpers.h"
6 #include "base/logging.h"
7 #include "base/run_loop.h"
8 #include "chrome/gpu/arc_gpu_video_decode_accelerator.h"
9 #include "content/public/common/gpu_video_decode_accelerator_factory.h"
10
11 #undef DVLOG
kcwu 2016/03/16 14:20:48 remember to remove before commit
Owen Lin 2016/03/18 05:49:36 Done.
12 #define DVLOG VLOG
13
14 namespace chromeos {
15 namespace arc {
16
17 ArcGpuVideoDecodeAccelerator::InputRecord::InputRecord(
18 int32_t bitstream_buffer_id,
19 uint32_t buffer_index,
20 int64_t timestamp)
21 : bitstream_buffer_id(bitstream_buffer_id),
22 buffer_index(buffer_index),
23 timestamp(timestamp) {}
24
25 ArcGpuVideoDecodeAccelerator::ArcGpuVideoDecodeAccelerator()
26 : pending_eos_output_buffer_(false),
27 arc_client_(nullptr),
28 next_bitstream_buffer_id_(0),
29 output_buffer_size_(0) {}
30
31 ArcGpuVideoDecodeAccelerator::~ArcGpuVideoDecodeAccelerator() {}
32
33 // An arbitrary chosen limit of the number of buffers. The number of
34 // buffers used is requested from the client side (less trusted).
35 static const size_t kMaxBufferCount = 128;
36
37 bool ArcGpuVideoDecodeAccelerator::Initialize(
38 const Config& config,
39 ArcVideoAccelerator::Client* client) {
40 DVLOG(5) << "Initialize(device=" << config.device_type
41 << ", input_pixel_format=" << config.input_pixel_format
42 << ", num_input_buffers=" << config.num_input_buffers << ")";
43 DCHECK(thread_checker_.CalledOnValidThread());
44 if (config.device_type != Config::DEVICE_DECODER)
45 return false;
46 DCHECK(client);
47 DCHECK(!arc_client_);
48 arc_client_ = client;
49
50 if (config.num_input_buffers > kMaxBufferCount) {
51 DLOG(ERROR) << "Request too many buffers: " << config.num_input_buffers;
52 return false;
53 }
54 input_buffer_info_.resize(config.num_input_buffers);
55
56 media::VideoDecodeAccelerator::Config vda_config;
57 switch (config.input_pixel_format) {
58 case HAL_PIXEL_FORMAT_H264:
59 vda_config.profile = media::H264PROFILE_MAIN;
60 break;
61 case HAL_PIXEL_FORMAT_VP8:
62 vda_config.profile = media::VP8PROFILE_ANY;
63 break;
64 default:
65 DLOG(ERROR) << "Unsupported input format: " << config.input_pixel_format;
66 return false;
67 }
68 vda_config.output_mode =
69 media::VideoDecodeAccelerator::Config::OutputMode::IMPORT;
70
71 scoped_ptr<content::GpuVideoDecodeAcceleratorFactory> vda_factory =
72 content::GpuVideoDecodeAcceleratorFactory::CreateWithNoGL();
73 vda_ = std::move(vda_factory->CreateVDA(this, vda_config));
74 if (!vda_) {
75 DLOG(ERROR) << "Failed to create VDA.";
76 return false;
77 }
78 return true;
79 }
80
81 void ArcGpuVideoDecodeAccelerator::SetNumberOfOutputBuffers(size_t number) {
kcwu 2016/03/17 13:10:47 what if SetNumberOfOutputBuffers called during dec
Owen Lin 2016/03/18 05:49:36 Each VDA should handle the case.
82 DVLOG(5) << "SetNumberOfOutputBuffers(" << number << ")";
83 DCHECK(thread_checker_.CalledOnValidThread());
84
85 if (number > kMaxBufferCount) {
86 DLOG(ERROR) << "Too many buffers: " << number;
87 arc_client_->OnError(INVALID_ARGUMENT);
88 return;
89 }
90
91 std::vector<media::PictureBuffer> buffers;
92 for (int32_t id = 0, n = number; id < n; ++id) {
93 // TODO: Make sure the |coded_size| is what we want.
94 buffers.push_back(media::PictureBuffer(id, coded_size_, 0));
95 }
96 vda_->AssignPictureBuffers(buffers);
kcwu 2016/03/17 13:10:47 I'm wondering if AssignPictureBuffers() is called
Owen Lin 2016/03/18 05:49:36 VDA should handle the error and call NotifyError(I
97
98 pending_import_buffer_.clear();
99 pending_import_buffer_.resize(number);
100 }
101
102 void ArcGpuVideoDecodeAccelerator::BindSharedMemory(PortType port,
103 uint32_t index,
104 int ashmem_fd,
105 off_t offset,
106 size_t length) {
107 DVLOG(5) << "ArcGVDA::BindSharedMemory, offset: " << offset
108 << ", length: " << length;
109 DCHECK(thread_checker_.CalledOnValidThread());
110
111 // Make sure we will close the file descriptor.
112 base::ScopedFD handle(ashmem_fd);
113 if (port != PORT_INPUT) {
114 DLOG(ERROR) << "SharedBuffer is only supported for input";
115 arc_client_->OnError(INVALID_ARGUMENT);
116 return;
117 }
118 if (!ValidatePortAndIndex(port, index)) {
119 arc_client_->OnError(INVALID_ARGUMENT);
120 return;
121 }
122 InputBufferInfo* input_info = &input_buffer_info_[index];
123 input_info->handle = std::move(handle);
124 input_info->offset = offset;
125 input_info->length = length;
126 }
127
128 void ArcGpuVideoDecodeAccelerator::BindDmabuf(PortType port,
129 uint32_t index,
130 int dmabuf_fd) {
131 DCHECK(thread_checker_.CalledOnValidThread());
132
133 // Make sure we will close the file descriptor.
134 base::ScopedFD handle(dmabuf_fd);
135 if (port != PORT_OUTPUT) {
136 DLOG(ERROR) << "GraphicBuffer is only supported for input";
137 arc_client_->OnError(INVALID_ARGUMENT);
138 return;
139 }
140 if (!ValidatePortAndIndex(port, index)) {
141 arc_client_->OnError(INVALID_ARGUMENT);
142 return;
143 }
144 pending_import_buffer_[index] = std::move(handle);
145 }
146
147 void ArcGpuVideoDecodeAccelerator::UseBuffer(PortType port,
kcwu 2016/03/17 13:10:47 what if UseBuffer called with index which is alrea
Owen Lin 2016/03/18 05:49:36 VDA should handle this.
148 uint32_t index,
149 const BufferMetadata& metadata) {
150 DVLOG(5) << "UseBuffer(port=" << port << ", index=" << index
151 << ", metadata=(bytes_used=" << metadata.bytes_used
152 << ", timestamp=" << metadata.timestamp << ")";
153 DCHECK(thread_checker_.CalledOnValidThread());
154 if (!ValidatePortAndIndex(port, index)) {
155 arc_client_->OnError(INVALID_ARGUMENT);
156 return;
157 }
158 switch (port) {
159 case PORT_INPUT: {
160 InputBufferInfo* input_info = &input_buffer_info_[index];
161 int32_t bitstream_buffer_id = next_bitstream_buffer_id_;
162 // Mask against 30 bits, to avoid (undefined) wraparound on signed
163 // integer.
164 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF;
165 SetInputRecord(bitstream_buffer_id, index, metadata.timestamp);
166 int dup_fd = HANDLE_EINTR(dup(input_info->handle.get()));
167 if (dup_fd < 0) {
168 DLOG(ERROR) << "dup() failed.";
169 arc_client_->OnError(PLATFORM_FAILURE);
170 return;
171 }
172 vda_->Decode(media::BitstreamBuffer(
kcwu 2016/03/17 13:10:47 We need to check |vda_| is valid for all methods t
Owen Lin 2016/03/18 05:49:36 Yes, we need. Code modified.
173 bitstream_buffer_id, base::SharedMemoryHandle(dup_fd, true),
174 metadata.bytes_used, input_info->offset));
175 if (metadata.flags & BUFFER_FLAG_EOS) {
176 vda_->Flush(true);
177 }
178 break;
179 }
180 case PORT_OUTPUT: {
181 SendEosIfNeededOrReusePicture(index);
182 break;
183 }
184 default:
185 NOTREACHED();
186 }
187 }
188
189 void ArcGpuVideoDecodeAccelerator::Reset() {
190 DCHECK(thread_checker_.CalledOnValidThread());
191 base::RunLoop loop;
192 reset_done_callback_ = loop.QuitClosure();
193 DCHECK(vda_);
194 vda_->Reset();
195 base::MessageLoop::ScopedNestableTaskAllower allow(
196 base::MessageLoop::current());
197 // Wait for the ResetDone callback.
198 loop.Run();
199 }
200
201 void ArcGpuVideoDecodeAccelerator::ProvidePictureBuffers(
202 size_t requested_num_of_buffers,
203 const gfx::Size& dimensions,
204 uint32_t texture_target) {
205 DVLOG(5) << "ProvidePictureBuffers("
206 << "requested_num_of_buffers=" << requested_num_of_buffers
207 << ", dimensions=" << dimensions.ToString() << ")";
208 DCHECK(thread_checker_.CalledOnValidThread());
209 coded_size_ = dimensions;
210 // TODO(owenlin): use VDA::GetOutputFormat() here and calculate correct
211 // |buffer_size|.
212 VideoFormat video_format;
213 video_format.buffer_size = dimensions.GetArea() * 3 / 2;
214 output_buffer_size_ = video_format.buffer_size;
215 video_format.min_num_buffers = requested_num_of_buffers;
216 video_format.coded_width = dimensions.width();
217 video_format.coded_height = dimensions.height();
218 // TODO(owenlin): How to get visible size?
219 video_format.crop_top = 0;
220 video_format.crop_left = 0;
221 video_format.crop_width = dimensions.width();
222 video_format.crop_height = dimensions.height();
223 arc_client_->OnOutputFormatChanged(video_format);
224 }
225
226 void ArcGpuVideoDecodeAccelerator::DismissPictureBuffer(
227 int32_t picture_buffer) {
228 // no-op
229 }
230
231 void ArcGpuVideoDecodeAccelerator::PictureReady(const media::Picture& picture) {
232 DVLOG(5) << "PictureReady(picture_buffer_id=" << picture.picture_buffer_id()
233 << ", bitstream_buffer_id=" << picture.bitstream_buffer_id();
234 DCHECK(thread_checker_.CalledOnValidThread());
235
236 // Empty buffer, returned in Flushing.
237 if (picture.bitstream_buffer_id() == -1) {
238 buffers_pending_eos_.push(picture.picture_buffer_id());
239 return;
240 }
241 InputRecord* input_record = FindInputRecord(picture.bitstream_buffer_id());
242 if (input_record == nullptr) {
243 DLOG(ERROR) << "Cannot find for bitstream buffer id: "
244 << picture.bitstream_buffer_id();
245 arc_client_->OnError(PLATFORM_FAILURE);
246 return;
247 }
248
249 BufferMetadata metadata;
250 metadata.timestamp = input_record->timestamp;
251 metadata.bytes_used = output_buffer_size_;
252 arc_client_->OnBufferDone(PORT_OUTPUT, picture.picture_buffer_id(), metadata);
253 }
254
255 void ArcGpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer(
256 int32_t bitstream_buffer_id) {
257 DVLOG(5) << "NotifyEndOfBitstreamBuffer(" << bitstream_buffer_id << ")";
258 DCHECK(thread_checker_.CalledOnValidThread());
259 InputRecord* input_record = FindInputRecord(bitstream_buffer_id);
260 if (input_record == nullptr) {
261 arc_client_->OnError(PLATFORM_FAILURE);
262 return;
263 }
264 arc_client_->OnBufferDone(PORT_INPUT, input_record->buffer_index,
265 BufferMetadata());
266 }
267
268 void ArcGpuVideoDecodeAccelerator::NotifyFlushDone() {
269 DCHECK(thread_checker_.CalledOnValidThread());
270 pending_eos_output_buffer_ = true;
271 while (!buffers_pending_eos_.empty()) {
272 SendEosIfNeededOrReusePicture(buffers_pending_eos_.front());
273 buffers_pending_eos_.pop();
274 }
275 }
276
277 void ArcGpuVideoDecodeAccelerator::NotifyResetDone() {
278 DCHECK(thread_checker_.CalledOnValidThread());
279 base::ResetAndReturn(&reset_done_callback_).Run();
280 }
281
282 static ArcVideoAccelerator::Error ConvertErrorCode(
283 media::VideoDecodeAccelerator::Error error) {
284 switch (error) {
285 case media::VideoDecodeAccelerator::ILLEGAL_STATE:
286 return ArcVideoAccelerator::ILLEGAL_STATE;
287 case media::VideoDecodeAccelerator::INVALID_ARGUMENT:
288 return ArcVideoAccelerator::INVALID_ARGUMENT;
289 case media::VideoDecodeAccelerator::UNREADABLE_INPUT:
290 return ArcVideoAccelerator::UNREADABLE_INPUT;
291 case media::VideoDecodeAccelerator::PLATFORM_FAILURE:
292 return ArcVideoAccelerator::PLATFORM_FAILURE;
293 default:
294 DLOG(ERROR) << "Unknown error: " << error;
295 return ArcVideoAccelerator::PLATFORM_FAILURE;
296 }
297 }
298
299 void ArcGpuVideoDecodeAccelerator::NotifyError(
300 media::VideoDecodeAccelerator::Error error) {
301 DCHECK(thread_checker_.CalledOnValidThread());
302 DLOG(ERROR) << "Error notified: " << error;
303 arc_client_->OnError(ConvertErrorCode(error));
304 }
305
306 void ArcGpuVideoDecodeAccelerator::SendEosIfNeededOrReusePicture(
307 uint32_t index) {
308 if (pending_eos_output_buffer_) {
309 BufferMetadata metadata;
310 metadata.flags = BUFFER_FLAG_EOS;
311 arc_client_->OnBufferDone(PORT_OUTPUT, index, metadata);
312 pending_eos_output_buffer_ = false;
313 } else {
314 if (pending_import_buffer_[index].is_valid()) {
315 std::vector<gfx::GpuMemoryBufferHandle> buffers;
316 buffers.push_back(gfx::GpuMemoryBufferHandle());
317 buffers.back().native_pixmap_handle.fd =
318 base::FileDescriptor(pending_import_buffer_[index].release(), true);
319 vda_->ImportBufferForPicture(index, buffers);
320 DCHECK(!pending_import_buffer_[index].is_valid());
321 } else {
322 vda_->ReusePictureBuffer(index);
323 }
324 }
325 }
326
327 void ArcGpuVideoDecodeAccelerator::SetInputRecord(int32_t bitstream_buffer_id,
328 uint32_t buffer_index,
329 int64_t timestamp) {
330 input_records_.push_front(
331 InputRecord(bitstream_buffer_id, buffer_index, timestamp));
332 // The same value copied from media::GpuVideoDecoder.
333 const size_t kMaxNumberOfInputRecords = 128;
334 if (input_records_.size() > kMaxNumberOfInputRecords)
335 input_records_.pop_back();
336 }
337
338 ArcGpuVideoDecodeAccelerator::InputRecord*
339 ArcGpuVideoDecodeAccelerator::FindInputRecord(int32_t bitstream_buffer_id) {
340 for (auto& record : input_records_) {
341 if (record.bitstream_buffer_id == bitstream_buffer_id)
342 return &record;
343 }
344 return nullptr;
345 }
346
347 bool ArcGpuVideoDecodeAccelerator::ValidatePortAndIndex(PortType port,
348 uint32_t index) {
349 switch (port) {
350 case PORT_INPUT:
351 if (index >= input_buffer_info_.size()) {
352 DLOG(ERROR) << "Invalid index: " << index;
353 return false;
354 }
355 return true;
356 case PORT_OUTPUT:
357 if (index >= pending_import_buffer_.size()) {
358 DLOG(ERROR) << "Invalid index: " << index;
359 return false;
360 }
361 return true;
362 default:
363 DLOG(ERROR) << "Invalid port: " << port;
364 return false;
365 }
366 }
367
368 } // namespace arc
369 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/gpu/arc_gpu_video_decode_accelerator.h ('k') | chrome/gpu/arc_video_accelerator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698