OLD | NEW |
---|---|
(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, ×tamp); | |
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 | |
OLD | NEW |