| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/gpu/arc_gpu_video_decode_accelerator.h" | 5 #include "chrome/gpu/arc_gpu_video_decode_accelerator.h" |
| 6 | 6 |
| 7 #include "base/callback_helpers.h" | 7 #include "base/callback_helpers.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
| 10 #include "content/public/gpu/gpu_video_decode_accelerator_factory.h" | 10 #include "content/public/gpu/gpu_video_decode_accelerator_factory.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 | 26 |
| 27 ArcGpuVideoDecodeAccelerator::InputBufferInfo::InputBufferInfo( | 27 ArcGpuVideoDecodeAccelerator::InputBufferInfo::InputBufferInfo( |
| 28 InputBufferInfo&& other) | 28 InputBufferInfo&& other) |
| 29 : handle(std::move(other.handle)), | 29 : handle(std::move(other.handle)), |
| 30 offset(other.offset), | 30 offset(other.offset), |
| 31 length(other.length) {} | 31 length(other.length) {} |
| 32 | 32 |
| 33 ArcGpuVideoDecodeAccelerator::InputBufferInfo::~InputBufferInfo() {} | 33 ArcGpuVideoDecodeAccelerator::InputBufferInfo::~InputBufferInfo() {} |
| 34 | 34 |
| 35 ArcGpuVideoDecodeAccelerator::ArcGpuVideoDecodeAccelerator() | 35 ArcGpuVideoDecodeAccelerator::ArcGpuVideoDecodeAccelerator() |
| 36 : pending_eos_output_buffer_(false), | 36 : arc_client_(nullptr), |
| 37 arc_client_(nullptr), | |
| 38 next_bitstream_buffer_id_(0), | 37 next_bitstream_buffer_id_(0), |
| 39 output_buffer_size_(0) {} | 38 output_buffer_size_(0) {} |
| 40 | 39 |
| 41 ArcGpuVideoDecodeAccelerator::~ArcGpuVideoDecodeAccelerator() {} | 40 ArcGpuVideoDecodeAccelerator::~ArcGpuVideoDecodeAccelerator() {} |
| 42 | 41 |
| 43 namespace { | 42 namespace { |
| 44 | 43 |
| 45 // An arbitrary chosen limit of the number of buffers. The number of | 44 // An arbitrary chosen limit of the number of buffers. The number of |
| 46 // buffers used is requested from the untrusted client side. | 45 // buffers used is requested from the untrusted client side. |
| 47 const size_t kMaxBufferCount = 128; | 46 const size_t kMaxBufferCount = 128; |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 int dup_fd = HANDLE_EINTR(dup(input_info->handle.get())); | 200 int dup_fd = HANDLE_EINTR(dup(input_info->handle.get())); |
| 202 if (dup_fd < 0) { | 201 if (dup_fd < 0) { |
| 203 DLOG(ERROR) << "dup() failed."; | 202 DLOG(ERROR) << "dup() failed."; |
| 204 arc_client_->OnError(PLATFORM_FAILURE); | 203 arc_client_->OnError(PLATFORM_FAILURE); |
| 205 return; | 204 return; |
| 206 } | 205 } |
| 207 CreateInputRecord(bitstream_buffer_id, index, metadata.timestamp); | 206 CreateInputRecord(bitstream_buffer_id, index, metadata.timestamp); |
| 208 vda_->Decode(media::BitstreamBuffer( | 207 vda_->Decode(media::BitstreamBuffer( |
| 209 bitstream_buffer_id, base::SharedMemoryHandle(dup_fd, true), | 208 bitstream_buffer_id, base::SharedMemoryHandle(dup_fd, true), |
| 210 metadata.bytes_used, input_info->offset)); | 209 metadata.bytes_used, input_info->offset)); |
| 211 if (metadata.flags & BUFFER_FLAG_EOS) { | 210 break; |
| 212 vda_->Flush(); | 211 } |
| 212 case PORT_OUTPUT: { |
| 213 // is_valid() is true for the first time the buffer is passed to the VDA. |
| 214 // In that case, VDA needs to import the buffer first. |
| 215 if (buffers_pending_import_[index].is_valid()) { |
| 216 gfx::GpuMemoryBufferHandle handle; |
| 217 #if defined(USE_OZONE) |
| 218 handle.native_pixmap_handle.fd = base::FileDescriptor( |
| 219 buffers_pending_import_[index].release(), true); |
| 220 #endif |
| 221 vda_->ImportBufferForPicture(index, {handle}); |
| 222 } else { |
| 223 vda_->ReusePictureBuffer(index); |
| 213 } | 224 } |
| 214 break; | 225 break; |
| 215 } | 226 } |
| 216 case PORT_OUTPUT: { | |
| 217 SendEosIfNeededOrReusePicture(index); | |
| 218 break; | |
| 219 } | |
| 220 default: | 227 default: |
| 221 NOTREACHED(); | 228 NOTREACHED(); |
| 222 } | 229 } |
| 223 } | 230 } |
| 224 | 231 |
| 225 void ArcGpuVideoDecodeAccelerator::Reset() { | 232 void ArcGpuVideoDecodeAccelerator::Reset() { |
| 226 DCHECK(thread_checker_.CalledOnValidThread()); | 233 DCHECK(thread_checker_.CalledOnValidThread()); |
| 227 if (!vda_) { | 234 if (!vda_) { |
| 228 DLOG(ERROR) << "VDA not initialized"; | 235 DLOG(ERROR) << "VDA not initialized"; |
| 229 return; | 236 return; |
| 230 } | 237 } |
| 231 vda_->Reset(); | 238 vda_->Reset(); |
| 232 } | 239 } |
| 233 | 240 |
| 241 void ArcGpuVideoDecodeAccelerator::Flush() { |
| 242 DCHECK(thread_checker_.CalledOnValidThread()); |
| 243 if (!vda_) { |
| 244 DLOG(ERROR) << "VDA not initialized"; |
| 245 return; |
| 246 } |
| 247 vda_->Flush(); |
| 248 } |
| 249 |
| 234 void ArcGpuVideoDecodeAccelerator::ProvidePictureBuffers( | 250 void ArcGpuVideoDecodeAccelerator::ProvidePictureBuffers( |
| 235 uint32_t requested_num_of_buffers, | 251 uint32_t requested_num_of_buffers, |
| 236 uint32_t textures_per_buffer, | 252 uint32_t textures_per_buffer, |
| 237 const gfx::Size& dimensions, | 253 const gfx::Size& dimensions, |
| 238 uint32_t texture_target) { | 254 uint32_t texture_target) { |
| 239 DVLOG(5) << "ProvidePictureBuffers(" | 255 DVLOG(5) << "ProvidePictureBuffers(" |
| 240 << "requested_num_of_buffers=" << requested_num_of_buffers | 256 << "requested_num_of_buffers=" << requested_num_of_buffers |
| 241 << ", dimensions=" << dimensions.ToString() << ")"; | 257 << ", dimensions=" << dimensions.ToString() << ")"; |
| 242 DCHECK(thread_checker_.CalledOnValidThread()); | 258 DCHECK(thread_checker_.CalledOnValidThread()); |
| 243 coded_size_ = dimensions; | 259 coded_size_ = dimensions; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 void ArcGpuVideoDecodeAccelerator::DismissPictureBuffer( | 295 void ArcGpuVideoDecodeAccelerator::DismissPictureBuffer( |
| 280 int32_t picture_buffer) { | 296 int32_t picture_buffer) { |
| 281 // no-op | 297 // no-op |
| 282 } | 298 } |
| 283 | 299 |
| 284 void ArcGpuVideoDecodeAccelerator::PictureReady(const media::Picture& picture) { | 300 void ArcGpuVideoDecodeAccelerator::PictureReady(const media::Picture& picture) { |
| 285 DVLOG(5) << "PictureReady(picture_buffer_id=" << picture.picture_buffer_id() | 301 DVLOG(5) << "PictureReady(picture_buffer_id=" << picture.picture_buffer_id() |
| 286 << ", bitstream_buffer_id=" << picture.bitstream_buffer_id(); | 302 << ", bitstream_buffer_id=" << picture.bitstream_buffer_id(); |
| 287 DCHECK(thread_checker_.CalledOnValidThread()); | 303 DCHECK(thread_checker_.CalledOnValidThread()); |
| 288 | 304 |
| 289 // Empty buffer, returned in Flushing. | |
| 290 if (picture.bitstream_buffer_id() == -1) { | |
| 291 buffers_pending_eos_.push(picture.picture_buffer_id()); | |
| 292 return; | |
| 293 } | |
| 294 InputRecord* input_record = FindInputRecord(picture.bitstream_buffer_id()); | 305 InputRecord* input_record = FindInputRecord(picture.bitstream_buffer_id()); |
| 295 if (input_record == nullptr) { | 306 if (input_record == nullptr) { |
| 296 DLOG(ERROR) << "Cannot find for bitstream buffer id: " | 307 DLOG(ERROR) << "Cannot find for bitstream buffer id: " |
| 297 << picture.bitstream_buffer_id(); | 308 << picture.bitstream_buffer_id(); |
| 298 arc_client_->OnError(PLATFORM_FAILURE); | 309 arc_client_->OnError(PLATFORM_FAILURE); |
| 299 return; | 310 return; |
| 300 } | 311 } |
| 301 | 312 |
| 302 BufferMetadata metadata; | 313 BufferMetadata metadata; |
| 303 metadata.timestamp = input_record->timestamp; | 314 metadata.timestamp = input_record->timestamp; |
| 304 metadata.bytes_used = output_buffer_size_; | 315 metadata.bytes_used = output_buffer_size_; |
| 305 arc_client_->OnBufferDone(PORT_OUTPUT, picture.picture_buffer_id(), metadata); | 316 arc_client_->OnBufferDone(PORT_OUTPUT, picture.picture_buffer_id(), metadata); |
| 306 } | 317 } |
| 307 | 318 |
| 308 void ArcGpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( | 319 void ArcGpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( |
| 309 int32_t bitstream_buffer_id) { | 320 int32_t bitstream_buffer_id) { |
| 310 DVLOG(5) << "NotifyEndOfBitstreamBuffer(" << bitstream_buffer_id << ")"; | 321 DVLOG(5) << "NotifyEndOfBitstreamBuffer(" << bitstream_buffer_id << ")"; |
| 311 DCHECK(thread_checker_.CalledOnValidThread()); | 322 DCHECK(thread_checker_.CalledOnValidThread()); |
| 312 InputRecord* input_record = FindInputRecord(bitstream_buffer_id); | 323 InputRecord* input_record = FindInputRecord(bitstream_buffer_id); |
| 313 if (input_record == nullptr) { | 324 if (input_record == nullptr) { |
| 314 arc_client_->OnError(PLATFORM_FAILURE); | 325 arc_client_->OnError(PLATFORM_FAILURE); |
| 315 return; | 326 return; |
| 316 } | 327 } |
| 317 arc_client_->OnBufferDone(PORT_INPUT, input_record->buffer_index, | 328 arc_client_->OnBufferDone(PORT_INPUT, input_record->buffer_index, |
| 318 BufferMetadata()); | 329 BufferMetadata()); |
| 319 } | 330 } |
| 320 | 331 |
| 321 void ArcGpuVideoDecodeAccelerator::NotifyFlushDone() { | 332 void ArcGpuVideoDecodeAccelerator::NotifyFlushDone() { |
| 322 DCHECK(thread_checker_.CalledOnValidThread()); | 333 DCHECK(thread_checker_.CalledOnValidThread()); |
| 323 pending_eos_output_buffer_ = true; | 334 arc_client_->OnFlushDone(); |
| 324 while (!buffers_pending_eos_.empty()) { | |
| 325 SendEosIfNeededOrReusePicture(buffers_pending_eos_.front()); | |
| 326 buffers_pending_eos_.pop(); | |
| 327 } | |
| 328 } | 335 } |
| 329 | 336 |
| 330 void ArcGpuVideoDecodeAccelerator::NotifyResetDone() { | 337 void ArcGpuVideoDecodeAccelerator::NotifyResetDone() { |
| 331 DCHECK(thread_checker_.CalledOnValidThread()); | 338 DCHECK(thread_checker_.CalledOnValidThread()); |
| 332 arc_client_->OnResetDone(); | 339 arc_client_->OnResetDone(); |
| 333 } | 340 } |
| 334 | 341 |
| 335 static ArcVideoAccelerator::Error ConvertErrorCode( | 342 static ArcVideoAccelerator::Error ConvertErrorCode( |
| 336 media::VideoDecodeAccelerator::Error error) { | 343 media::VideoDecodeAccelerator::Error error) { |
| 337 switch (error) { | 344 switch (error) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 349 } | 356 } |
| 350 } | 357 } |
| 351 | 358 |
| 352 void ArcGpuVideoDecodeAccelerator::NotifyError( | 359 void ArcGpuVideoDecodeAccelerator::NotifyError( |
| 353 media::VideoDecodeAccelerator::Error error) { | 360 media::VideoDecodeAccelerator::Error error) { |
| 354 DCHECK(thread_checker_.CalledOnValidThread()); | 361 DCHECK(thread_checker_.CalledOnValidThread()); |
| 355 DLOG(ERROR) << "Error notified: " << error; | 362 DLOG(ERROR) << "Error notified: " << error; |
| 356 arc_client_->OnError(ConvertErrorCode(error)); | 363 arc_client_->OnError(ConvertErrorCode(error)); |
| 357 } | 364 } |
| 358 | 365 |
| 359 void ArcGpuVideoDecodeAccelerator::SendEosIfNeededOrReusePicture( | |
| 360 uint32_t index) { | |
| 361 if (pending_eos_output_buffer_) { | |
| 362 BufferMetadata metadata; | |
| 363 metadata.flags = BUFFER_FLAG_EOS; | |
| 364 arc_client_->OnBufferDone(PORT_OUTPUT, index, metadata); | |
| 365 pending_eos_output_buffer_ = false; | |
| 366 } else { | |
| 367 if (buffers_pending_import_[index].is_valid()) { | |
| 368 std::vector<gfx::GpuMemoryBufferHandle> buffers; | |
| 369 buffers.push_back(gfx::GpuMemoryBufferHandle()); | |
| 370 #if defined(USE_OZONE) | |
| 371 buffers.back().native_pixmap_handle.fd = | |
| 372 base::FileDescriptor(buffers_pending_import_[index].release(), true); | |
| 373 #endif | |
| 374 vda_->ImportBufferForPicture(index, buffers); | |
| 375 } else { | |
| 376 vda_->ReusePictureBuffer(index); | |
| 377 } | |
| 378 } | |
| 379 } | |
| 380 | |
| 381 void ArcGpuVideoDecodeAccelerator::CreateInputRecord( | 366 void ArcGpuVideoDecodeAccelerator::CreateInputRecord( |
| 382 int32_t bitstream_buffer_id, | 367 int32_t bitstream_buffer_id, |
| 383 uint32_t buffer_index, | 368 uint32_t buffer_index, |
| 384 int64_t timestamp) { | 369 int64_t timestamp) { |
| 385 input_records_.push_front( | 370 input_records_.push_front( |
| 386 InputRecord(bitstream_buffer_id, buffer_index, timestamp)); | 371 InputRecord(bitstream_buffer_id, buffer_index, timestamp)); |
| 387 | 372 |
| 388 // The same value copied from media::GpuVideoDecoder. The input record is | 373 // The same value copied from media::GpuVideoDecoder. The input record is |
| 389 // needed when the input buffer or the corresponding output buffer are | 374 // needed when the input buffer or the corresponding output buffer are |
| 390 // returned from VDA. However there is no guarantee how much buffers will be | 375 // returned from VDA. However there is no guarantee how much buffers will be |
| (...skipping 29 matching lines...) Expand all Loading... |
| 420 } | 405 } |
| 421 return true; | 406 return true; |
| 422 default: | 407 default: |
| 423 DLOG(ERROR) << "Invalid port: " << port; | 408 DLOG(ERROR) << "Invalid port: " << port; |
| 424 return false; | 409 return false; |
| 425 } | 410 } |
| 426 } | 411 } |
| 427 | 412 |
| 428 } // namespace arc | 413 } // namespace arc |
| 429 } // namespace chromeos | 414 } // namespace chromeos |
| OLD | NEW |