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

Side by Side Diff: content/common/gpu/media/arc/arc_gpu_video_decode_accelerator.cc

Issue 1549473002: Add ArcGpuVideoDecodeAccelerator. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years 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 2015 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 "content/common/gpu/media/arc/arc_gpu_video_decode_accelerator.h"
9
10 namespace content {
11 namespace arc {
12
13 ArcGpuVideoDecodeAccelerator::BufferInfo::BufferInfo()
14 : state(OWNED_BY_CLIENT), offset(0), length(0) {}
15
16 ArcGpuVideoDecodeAccelerator::PortInfo::PortInfo()
17 : memory_type(MEMORY_DMABUF) {}
18
19 ArcGpuVideoDecodeAccelerator::InputRecord::InputRecord(
20 int32_t bitstream_buffer_id,
21 uint32_t index,
22 int64_t timestamp)
23 : bitstream_buffer_id(bitstream_buffer_id),
24 index(index),
25 timestamp(timestamp) {}
26
27 ArcGpuVideoDecodeAccelerator::ArcGpuVideoDecodeAccelerator()
28 : arc_client_(nullptr) {}
29
30 status_t ArcGpuVideoDecodeAccelerator::initialize(
31 DeviceType device,
32 ArcVideoAccelerator::Client* client) {
33 if (device != DEVICE_DECODER)
34 return EINVAL;
35 DCHECK(client);
36 DCHECK(!arc_client_);
37 arc_client_ = client;
38 return 0;
39 }
40
41 status_t ArcGpuVideoDecodeAccelerator::setBufferCount(PortType port,
42 size_t* count) {
43 if (arc_vda_ == nullptr) {
44 DVLOG(1) << "Must call setBufferFormat before setBufferCount";
45 return EINVAL;
46 }
47 if (port == PORT_OUTPUT) {
48 size_t try_count = *count;
49 for (; try_count > 0; --try_count) {
50 if (arc_vda_->SetPictureCount(*count)) {
51 *count = try_count;
52 break;
53 }
54 }
55 if (try_count == 0) {
56 DVLOG(1) << "Failed to find valid buffer count";
57 return EIO;
58 }
59 }
60 PortInfo* port_info = &port_info_[port];
kcwu 2015/12/23 06:25:43 validate value of |port|
Owen Lin 2015/12/31 07:22:14 Done.
61 port_info->buffers.clear();
62 port_info->buffers.resize(*count);
63 return 0;
64 }
65
66 status_t ArcGpuVideoDecodeAccelerator::setBufferFormat(
67 PortType port,
68 const BufferFormat& format) {
69 PortInfo* port_info = &port_info_[port];
70 switch (port) {
71 case PORT_INPUT:
72 if (format.memory_type != MEMORY_SHARED_MEMORY) {
73 DVLOG(1) << "Only SharedMemory is supported for input buffers";
74 return EINVAL;
75 }
76 port_info->memory_type = format.memory_type;
77 switch (format.pixel_format) {
78 case HAL_PIXEL_FORMAT_H264:
79 case HAL_PIXEL_FORMAT_VP8:
80 arc_vda_ = nullptr; // TODO(owenlin): Change to real implementation.
81 break;
82 default:
83 DVLOG(1) << "Unsupported input format: " << format.pixel_format;
84 return EINVAL;
85 }
86 break;
87 case PORT_OUTPUT:
88 if (format.memory_type != MEMORY_DMABUF) {
89 DVLOG(1) << "Only DMA buffer is supported for output buffers";
90 return EINVAL;
91 }
92 port_info->memory_type = format.memory_type;
93 break;
94 default:
95 NOTREACHED();
kcwu 2015/12/23 06:25:43 return EINVAL; |port| may come from less trusted c
Owen Lin 2015/12/31 07:22:14 Done.
96 }
97 return 0;
98 }
99
100 ArcGpuVideoDecodeAccelerator::BufferInfo*
101 ArcGpuVideoDecodeAccelerator::GetBufferInfo(PortType port, uint32_t index) {
102 if (port < 0 || port >= PORT_COUNT)
103 return nullptr;
104 std::vector<BufferInfo>* buffers = &port_info_[port].buffers;
kcwu 2015/12/23 06:25:43 How about: auto& buffers = port_info_[port].buffer
Owen Lin 2015/12/31 07:22:14 Done.
105 return index >= buffers->size() ? nullptr : &buffers->at(index);
106 }
107
108 status_t ArcGpuVideoDecodeAccelerator::bindSharedBuffer(PortType port,
109 uint32_t index,
110 int ashmem_fd,
111 size_t offset,
112 size_t length) {
113 // Make sure we will close the file descriptor.
114 base::ScopedFD handle(ashmem_fd);
115 PortInfo* port_info = &port_info_[port];
kcwu 2015/12/23 06:25:43 Value of |port| need to validate. Please either 1.
Owen Lin 2015/12/31 07:22:14 Done.
116 if (port_info->memory_type != MEMORY_SHARED_MEMORY) {
117 DVLOG(1) << "Unmatched memory type: " << port_info->memory_type;
118 return EINVAL;
119 }
120 BufferInfo* buffer_info = GetBufferInfo(port, index);
121 if (buffer_info == nullptr) {
122 DVLOG(1) << "Invalid buffer port: " << port << " index: " << index;
123 return EINVAL;
124 }
125 if (buffer_info->state != OWNED_BY_CLIENT) {
126 DVLOG(1) << "Cannot bind a buffer while in use";
127 return EINVAL;
128 }
129 buffer_info->handle = std::move(handle);
130 buffer_info->offset = offset;
131 buffer_info->length = length;
132 return 0;
133 }
134
135 status_t ArcGpuVideoDecodeAccelerator::bindGraphicBuffer(PortType port,
136 uint32_t index,
137 int dmabuf_fd) {
138 // Make sure we will close the file descriptor.
139 base::ScopedFD handle(dmabuf_fd);
140 PortInfo* port_info = &port_info_[port];
kcwu 2015/12/23 06:25:43 Ditto, check value of |port|
Owen Lin 2015/12/31 07:22:14 Done.
141 if (port_info->memory_type != MEMORY_DMABUF) {
142 DVLOG(1) << "Unmatched memory type: " << port_info->memory_type;
143 return EINVAL;
144 }
145 BufferInfo* buffer_info = GetBufferInfo(port, index);
146 if (buffer_info == nullptr) {
147 DVLOG(1) << "Invalid buffer port: " << port << " index: " << index;
148 return EINVAL;
149 }
150 if (buffer_info->state != OWNED_BY_CLIENT) {
151 DVLOG(1) << "Cannot bind a buffer while in use";
152 return EINVAL;
153 }
154 return arc_vda_->AssignPictureBuffer(index, std::move(handle)) ? 0 : EIO;
155 }
156
157 void ArcGpuVideoDecodeAccelerator::useBuffer(PortType port,
158 uint32_t index,
159 const BufferMetadata& metadata) {
160 BufferInfo* buffer_info = GetBufferInfo(port, index);
161 if (buffer_info == nullptr) {
162 DVLOG(1) << "Invalid buffer port: " << port << ", index: " << index;
163 arc_client_->onError(INVALID_ARGUMENT);
164 return;
165 }
166 if (!buffer_info->handle.is_valid()) {
167 DVLOG(1) << "Must bind a buffer before using it, port: " << port
168 << ", index: " << index;
169 arc_client_->onError(ILLEGAL_STATE);
170 return;
171 }
172 buffer_info->state = OWNED_BY_US;
173 switch (port) {
174 case PORT_INPUT: {
175 if (metadata.flags & BUFFER_FLAG_EOS) {
176 // Ask VDA to return all output pictures so that we can output an EOS
177 // picture when Flush() is done.
178 arc_vda_->Flush(true);
179 }
180 if (metadata.bytes_used > 0) {
181 int32_t bitstream_buffer_id = bitstream_buffer_serial_++;
182 if (bitstream_buffer_serial_ < 0)
183 bitstream_buffer_serial_ = 0;
184 SetInputRecord(bitstream_buffer_id, index, metadata.timestamp);
185 base::SharedMemoryHandle shared_memory_handle(buffer_info->handle.get(),
kcwu 2015/12/23 06:25:43 when will the handle be closed?
Owen Lin 2015/12/31 07:22:14 For now, it will be close when this ArcGVDA destro
186 false);
187 // TODO(owenlin): Make BitstreamBuffer surpport offset and use here.
188 media::BitstreamBuffer bitstream_buffer(
189 bitstream_buffer_id, shared_memory_handle, buffer_info->length);
190 buffer_info->state = OWNED_BY_VDA;
191 arc_vda_->Decode(bitstream_buffer);
192 } else {
193 buffer_info->state = OWNED_BY_CLIENT;
194 arc_client_->onBufferDone(PORT_INPUT, index, BufferMetadata());
195 }
196 break;
197 }
198 case PORT_OUTPUT: {
199 SendEosIfNeededOrReusePicture(index, buffer_info);
200 break;
201 }
202 default:
203 NOTREACHED();
204 }
205 }
206
207 void ArcGpuVideoDecodeAccelerator::reset() {
208 base::RunLoop loop;
209 reset_done_callback_ = loop.QuitClosure();
210 arc_vda_->Reset();
211 base::MessageLoop::ScopedNestableTaskAllower allow(
212 base::MessageLoop::current());
213 // Wait for the ResetDone callback.
214 loop.Run();
215 }
216
217 void ArcGpuVideoDecodeAccelerator::RequestPictureBuffers(
218 size_t requested_num_of_buffers,
219 const gfx::Size& coded_size,
220 const gfx::Rect& crop_rect) {
221 // TODO(owenlin): Think if we need to handle the pixel format.
222 // It looks like the flexible pixel format is good enough.
223 VideoFormat video_format;
224 video_format.min_num_buffers = requested_num_of_buffers;
225 video_format.coded_width = coded_size.width();
226 video_format.coded_height = coded_size.height();
227 video_format.crop_left = crop_rect.x();
228 video_format.crop_top = crop_rect.y();
229 video_format.crop_width = crop_rect.width();
230 video_format.crop_height = crop_rect.height();
231 arc_client_->onOutputFormatChanged(video_format);
232 }
233
234 void ArcGpuVideoDecodeAccelerator::PictureReady(const media::Picture& picture) {
235 BufferInfo* output_buffer =
236 GetBufferInfo(PORT_OUTPUT, picture.picture_buffer_id());
237 CHECK_NE(output_buffer, nullptr);
238
239 // Empty buffer, returned in Flushing.
240 if (picture.bitstream_buffer_id() == -1) {
241 output_buffer->state = OWNED_BY_US;
242 } else {
243 BufferMetadata metadata;
244 uint32_t index = 0;
245 GetInputRecord(picture.bitstream_buffer_id(), &index, &metadata.timestamp);
246 output_buffer->state = OWNED_BY_CLIENT;
247 arc_client_->onBufferDone(PORT_OUTPUT, picture.picture_buffer_id(),
248 metadata);
249 }
250 }
251
252 void ArcGpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer(
253 int32_t bitstream_buffer_id) {
254 int64_t timestamp = 0;
255 uint32_t index = 0;
256 GetInputRecord(bitstream_buffer_id, &index, &timestamp);
257 BufferInfo* buffer_info = GetBufferInfo(PORT_OUTPUT, index);
258 CHECK(buffer_info);
259 buffer_info->state = OWNED_BY_CLIENT;
260 arc_client_->onBufferDone(PORT_INPUT, bitstream_buffer_id, BufferMetadata());
261 }
262
263 void ArcGpuVideoDecodeAccelerator::NotifyFlushDone() {
264 pending_eos_output_buffer_ = true;
265 std::vector<BufferInfo>* buffers = &port_info_[PORT_OUTPUT].buffers;
266 for (size_t i = 0, n = buffers->size(); i < n; ++i) {
267 BufferInfo* info = &buffers->at(i);
268 if (info->state == OWNED_BY_US)
269 SendEosIfNeededOrReusePicture(i, info);
270 }
271 }
272
273 void ArcGpuVideoDecodeAccelerator::NotifyResetDone() {
274 base::ResetAndReturn(&reset_done_callback_).Run();
275 }
276
277 static ArcVideoAccelerator::Error convertErrorCode(
kcwu 2015/12/23 06:25:43 s/convert/Convert/
Owen Lin 2015/12/31 07:22:14 Done.
278 ArcVideoDecodeAccelerator::Error error) {
279 #define CASE(t) \
280 case ArcVideoDecodeAccelerator::t: \
281 return ArcVideoAccelerator::t
282 switch (error) {
283 CASE(ILLEGAL_STATE);
284 CASE(INVALID_ARGUMENT);
285 CASE(UNREADABLE_INPUT);
286 CASE(PLATFORM_FAILURE);
287 default:
288 NOTREACHED() << "Unknown error: " << error;
289 }
290 #undef CASE
291 return static_cast<ArcVideoAccelerator::Error>(error);
292 }
293
294 void ArcGpuVideoDecodeAccelerator::NotifyError(
295 ArcVideoDecodeAccelerator::Error error) {
296 arc_client_->onError(convertErrorCode(error));
297 }
298
299 void ArcGpuVideoDecodeAccelerator::SendEosIfNeededOrReusePicture(
300 uint32_t index,
301 BufferInfo* info) {
302 DCHECK_EQ(info->state, OWNED_BY_US);
303 if (pending_eos_output_buffer_) {
304 BufferMetadata metadata;
305 metadata.flags = BUFFER_FLAG_EOS;
306 info->state = OWNED_BY_CLIENT;
307 arc_client_->onBufferDone(PORT_OUTPUT, index, metadata);
308 pending_eos_output_buffer_ = false;
309 } else {
310 info->state = OWNED_BY_VDA;
311 arc_vda_->ReusePictureBuffer(index);
312 }
313 }
314
315 void ArcGpuVideoDecodeAccelerator::SetInputRecord(int32_t bitstream_buffer_id,
316 uint32_t index,
317 int64_t timestamp) {
318 input_records_.push_front(InputRecord(bitstream_buffer_id, index, timestamp));
319 // The value is copied from media::GpuVideoDecoder.
320 static const size_t kMaxInputBufferDataSize = 128;
kcwu 2015/12/23 06:25:43 s/static// local constant doesn't need static stor
Owen Lin 2015/12/31 07:22:14 Done.
321 if (input_records_.size() > kMaxInputBufferDataSize)
322 input_records_.pop_back();
323 }
324
325 void ArcGpuVideoDecodeAccelerator::GetInputRecord(int32_t bitstream_buffer_id,
326 uint32_t* index,
327 int64_t* timestamp) {
328 for (auto& data : input_records_) {
329 if (data.bitstream_buffer_id == bitstream_buffer_id) {
330 *index = data.index;
331 *timestamp = data.timestamp;
332 return;
333 }
334 }
335 NOTREACHED() << "Missing bitstream_buffer_id: " << bitstream_buffer_id;
336 }
337
338 } // arc
339 } // content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698