Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "media/gpu/v4l2_video_decode_accelerator.h" | 5 #include "media/gpu/v4l2_video_decode_accelerator.h" |
| 6 | 6 |
| 7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <fcntl.h> | 9 #include <fcntl.h> |
| 10 #include <linux/videodev2.h> | 10 #include <linux/videodev2.h> |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 193 DCHECK(!device_poll_thread_.IsRunning()); | 193 DCHECK(!device_poll_thread_.IsRunning()); |
| 194 | 194 |
| 195 // These maps have members that should be manually destroyed, e.g. file | 195 // These maps have members that should be manually destroyed, e.g. file |
| 196 // descriptors, mmap() segments, etc. | 196 // descriptors, mmap() segments, etc. |
| 197 DCHECK(input_buffer_map_.empty()); | 197 DCHECK(input_buffer_map_.empty()); |
| 198 DCHECK(output_buffer_map_.empty()); | 198 DCHECK(output_buffer_map_.empty()); |
| 199 } | 199 } |
| 200 | 200 |
| 201 bool V4L2VideoDecodeAccelerator::Initialize(const Config& config, | 201 bool V4L2VideoDecodeAccelerator::Initialize(const Config& config, |
| 202 Client* client) { | 202 Client* client) { |
| 203 DVLOGF(3) << "profile: " << config.profile | 203 DVLOGF(2) << "profile: " << config.profile |
| 204 << ", output_mode=" << static_cast<int>(config.output_mode); | 204 << ", output_mode=" << static_cast<int>(config.output_mode); |
| 205 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 205 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 206 DCHECK_EQ(decoder_state_, kUninitialized); | 206 DCHECK_EQ(decoder_state_, kUninitialized); |
| 207 | 207 |
| 208 if (config.is_encrypted()) { | 208 if (config.is_encrypted()) { |
| 209 NOTREACHED() << "Encrypted streams are not supported for this VDA"; | 209 NOTREACHED() << "Encrypted streams are not supported for this VDA"; |
| 210 return false; | 210 return false; |
| 211 } | 211 } |
| 212 | 212 |
| 213 if (config.output_mode != Config::OutputMode::ALLOCATE && | 213 if (config.output_mode != Config::OutputMode::ALLOCATE && |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 288 | 288 |
| 289 // InitializeTask will NOTIFY_ERROR on failure. | 289 // InitializeTask will NOTIFY_ERROR on failure. |
| 290 decoder_thread_.task_runner()->PostTask( | 290 decoder_thread_.task_runner()->PostTask( |
| 291 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::InitializeTask, | 291 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::InitializeTask, |
| 292 base::Unretained(this))); | 292 base::Unretained(this))); |
| 293 | 293 |
| 294 return true; | 294 return true; |
| 295 } | 295 } |
| 296 | 296 |
| 297 void V4L2VideoDecodeAccelerator::InitializeTask() { | 297 void V4L2VideoDecodeAccelerator::InitializeTask() { |
| 298 DVLOGF(3); | 298 DVLOGF(2); |
| 299 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 299 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 300 DCHECK_EQ(decoder_state_, kInitialized); | 300 DCHECK_EQ(decoder_state_, kInitialized); |
| 301 | 301 |
| 302 // Subscribe to the resolution change event. | 302 // Subscribe to the resolution change event. |
| 303 struct v4l2_event_subscription sub; | 303 struct v4l2_event_subscription sub; |
| 304 memset(&sub, 0, sizeof(sub)); | 304 memset(&sub, 0, sizeof(sub)); |
| 305 sub.type = V4L2_EVENT_SOURCE_CHANGE; | 305 sub.type = V4L2_EVENT_SOURCE_CHANGE; |
| 306 IOCTL_OR_ERROR_RETURN(VIDIOC_SUBSCRIBE_EVENT, &sub); | 306 IOCTL_OR_ERROR_RETURN(VIDIOC_SUBSCRIBE_EVENT, &sub); |
| 307 | 307 |
| 308 if (!CreateInputBuffers()) { | 308 if (!CreateInputBuffers()) { |
| 309 NOTIFY_ERROR(PLATFORM_FAILURE); | 309 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 310 return; | 310 return; |
| 311 } | 311 } |
| 312 | 312 |
| 313 decoder_cmd_supported_ = IsDecoderCmdSupported(); | 313 decoder_cmd_supported_ = IsDecoderCmdSupported(); |
| 314 | 314 |
| 315 if (!StartDevicePoll()) | 315 if (!StartDevicePoll()) |
| 316 return; | 316 return; |
| 317 } | 317 } |
| 318 | 318 |
| 319 void V4L2VideoDecodeAccelerator::Decode( | 319 void V4L2VideoDecodeAccelerator::Decode( |
| 320 const BitstreamBuffer& bitstream_buffer) { | 320 const BitstreamBuffer& bitstream_buffer) { |
| 321 DVLOGF(1) << "input_id=" << bitstream_buffer.id() | 321 DVLOGF(4) << "input_id=" << bitstream_buffer.id() |
| 322 << ", size=" << bitstream_buffer.size(); | 322 << ", size=" << bitstream_buffer.size(); |
| 323 DCHECK(decode_task_runner_->BelongsToCurrentThread()); | 323 DCHECK(decode_task_runner_->BelongsToCurrentThread()); |
| 324 | 324 |
| 325 if (bitstream_buffer.id() < 0) { | 325 if (bitstream_buffer.id() < 0) { |
| 326 LOGF(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id(); | 326 LOGF(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id(); |
| 327 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) | 327 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) |
| 328 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); | 328 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); |
| 329 NOTIFY_ERROR(INVALID_ARGUMENT); | 329 NOTIFY_ERROR(INVALID_ARGUMENT); |
| 330 return; | 330 return; |
| 331 } | 331 } |
| 332 | 332 |
| 333 // DecodeTask() will take care of running a DecodeBufferTask(). | 333 // DecodeTask() will take care of running a DecodeBufferTask(). |
| 334 decoder_thread_.task_runner()->PostTask( | 334 decoder_thread_.task_runner()->PostTask( |
| 335 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::DecodeTask, | 335 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::DecodeTask, |
| 336 base::Unretained(this), bitstream_buffer)); | 336 base::Unretained(this), bitstream_buffer)); |
| 337 } | 337 } |
| 338 | 338 |
| 339 void V4L2VideoDecodeAccelerator::AssignPictureBuffers( | 339 void V4L2VideoDecodeAccelerator::AssignPictureBuffers( |
| 340 const std::vector<PictureBuffer>& buffers) { | 340 const std::vector<PictureBuffer>& buffers) { |
| 341 DVLOGF(3) << "buffer_count=" << buffers.size(); | 341 DVLOGF(2) << "buffer_count=" << buffers.size(); |
| 342 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 342 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 343 | 343 |
| 344 decoder_thread_.task_runner()->PostTask( | 344 decoder_thread_.task_runner()->PostTask( |
| 345 FROM_HERE, | 345 FROM_HERE, |
| 346 base::Bind(&V4L2VideoDecodeAccelerator::AssignPictureBuffersTask, | 346 base::Bind(&V4L2VideoDecodeAccelerator::AssignPictureBuffersTask, |
| 347 base::Unretained(this), buffers)); | 347 base::Unretained(this), buffers)); |
| 348 } | 348 } |
| 349 | 349 |
| 350 void V4L2VideoDecodeAccelerator::AssignPictureBuffersTask( | 350 void V4L2VideoDecodeAccelerator::AssignPictureBuffersTask( |
| 351 const std::vector<PictureBuffer>& buffers) { | 351 const std::vector<PictureBuffer>& buffers) { |
| 352 DVLOGF(3); | 352 DVLOGF(2); |
| 353 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 353 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 354 DCHECK_EQ(decoder_state_, kAwaitingPictureBuffers); | 354 DCHECK_EQ(decoder_state_, kAwaitingPictureBuffers); |
| 355 | 355 |
| 356 uint32_t req_buffer_count = output_dpb_size_ + kDpbOutputBufferExtraCount; | 356 uint32_t req_buffer_count = output_dpb_size_ + kDpbOutputBufferExtraCount; |
| 357 if (image_processor_device_) | 357 if (image_processor_device_) |
| 358 req_buffer_count += kDpbOutputBufferExtraCountForImageProcessor; | 358 req_buffer_count += kDpbOutputBufferExtraCountForImageProcessor; |
| 359 | 359 |
| 360 if (buffers.size() < req_buffer_count) { | 360 if (buffers.size() < req_buffer_count) { |
| 361 LOGF(ERROR) << "Failed to provide requested picture buffers. (Got " | 361 LOGF(ERROR) << "Failed to provide requested picture buffers. (Got " |
| 362 << buffers.size() << ", requested " << req_buffer_count << ")"; | 362 << buffers.size() << ", requested " << req_buffer_count << ")"; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 432 ImportBufferForPictureTask( | 432 ImportBufferForPictureTask( |
| 433 output_record.picture_id, std::move(dmabuf_fds), | 433 output_record.picture_id, std::move(dmabuf_fds), |
| 434 egl_image_size_.width() * plane_horiz_bits_per_pixel / 8); | 434 egl_image_size_.width() * plane_horiz_bits_per_pixel / 8); |
| 435 } // else we'll get triggered via ImportBufferForPicture() from client. | 435 } // else we'll get triggered via ImportBufferForPicture() from client. |
| 436 | 436 |
| 437 DVLOGF(3) << "buffer[" << i << "]: picture_id=" << output_record.picture_id; | 437 DVLOGF(3) << "buffer[" << i << "]: picture_id=" << output_record.picture_id; |
| 438 } | 438 } |
| 439 | 439 |
| 440 if (output_mode_ == Config::OutputMode::ALLOCATE) { | 440 if (output_mode_ == Config::OutputMode::ALLOCATE) { |
| 441 DCHECK_EQ(kAwaitingPictureBuffers, decoder_state_); | 441 DCHECK_EQ(kAwaitingPictureBuffers, decoder_state_); |
| 442 DVLOGF(1) << "Change state to kDecoding"; | 442 DVLOGF(1) << "Change state to kDecoding"; |
|
Pawel Osciak
2017/05/23 09:49:21
2 or 3?
Owen Lin
2017/06/02 08:51:44
Done.
| |
| 443 decoder_state_ = kDecoding; | 443 decoder_state_ = kDecoding; |
| 444 if (reset_pending_) { | 444 if (reset_pending_) { |
| 445 FinishReset(); | 445 FinishReset(); |
| 446 return; | 446 return; |
| 447 } | 447 } |
| 448 ScheduleDecodeBufferTaskIfNeeded(); | 448 ScheduleDecodeBufferTaskIfNeeded(); |
| 449 } | 449 } |
| 450 } | 450 } |
| 451 | 451 |
| 452 void V4L2VideoDecodeAccelerator::CreateEGLImageFor( | 452 void V4L2VideoDecodeAccelerator::CreateEGLImageFor( |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 603 NOTIFY_ERROR(INVALID_ARGUMENT); | 603 NOTIFY_ERROR(INVALID_ARGUMENT); |
| 604 return; | 604 return; |
| 605 } | 605 } |
| 606 int adjusted_coded_width = stride * 8 / plane_horiz_bits_per_pixel; | 606 int adjusted_coded_width = stride * 8 / plane_horiz_bits_per_pixel; |
| 607 | 607 |
| 608 if (image_processor_device_ && !image_processor_) { | 608 if (image_processor_device_ && !image_processor_) { |
| 609 // This is the first buffer import. Create the image processor and change | 609 // This is the first buffer import. Create the image processor and change |
| 610 // the decoder state. The client may adjust the coded width. We don't have | 610 // the decoder state. The client may adjust the coded width. We don't have |
| 611 // the final coded size in AssignPictureBuffers yet. Use the adjusted coded | 611 // the final coded size in AssignPictureBuffers yet. Use the adjusted coded |
| 612 // width to create the image processor. | 612 // width to create the image processor. |
| 613 DVLOGF(3) << "Original egl_image_size=" << egl_image_size_.ToString() | 613 DVLOGF(3) << "Original egl_image_size=" << egl_image_size_.ToString() |
|
Pawel Osciak
2017/05/23 09:49:21
2?
Owen Lin
2017/06/02 08:51:43
Done.
| |
| 614 << ", adjusted coded width=" << adjusted_coded_width; | 614 << ", adjusted coded width=" << adjusted_coded_width; |
| 615 DCHECK_GE(adjusted_coded_width, egl_image_size_.width()); | 615 DCHECK_GE(adjusted_coded_width, egl_image_size_.width()); |
| 616 egl_image_size_.set_width(adjusted_coded_width); | 616 egl_image_size_.set_width(adjusted_coded_width); |
| 617 if (!CreateImageProcessor()) | 617 if (!CreateImageProcessor()) |
| 618 return; | 618 return; |
| 619 DCHECK_EQ(kAwaitingPictureBuffers, decoder_state_); | 619 DCHECK_EQ(kAwaitingPictureBuffers, decoder_state_); |
| 620 DVLOGF(1) << "Change state to kDecoding"; | 620 DVLOGF(2) << "Change state to kDecoding"; |
| 621 decoder_state_ = kDecoding; | 621 decoder_state_ = kDecoding; |
| 622 if (reset_pending_) { | 622 if (reset_pending_) { |
| 623 FinishReset(); | 623 FinishReset(); |
| 624 } | 624 } |
| 625 } else { | 625 } else { |
| 626 DCHECK_EQ(egl_image_size_.width(), adjusted_coded_width); | 626 DCHECK_EQ(egl_image_size_.width(), adjusted_coded_width); |
| 627 } | 627 } |
| 628 | 628 |
| 629 size_t index = iter - output_buffer_map_.begin(); | 629 size_t index = iter - output_buffer_map_.begin(); |
| 630 DCHECK_EQ(std::count(free_output_buffers_.begin(), free_output_buffers_.end(), | 630 DCHECK_EQ(std::count(free_output_buffers_.begin(), free_output_buffers_.end(), |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 651 iter->processor_output_fds.swap(dmabuf_fds); | 651 iter->processor_output_fds.swap(dmabuf_fds); |
| 652 free_output_buffers_.push_back(index); | 652 free_output_buffers_.push_back(index); |
| 653 if (decoder_state_ != kChangingResolution) { | 653 if (decoder_state_ != kChangingResolution) { |
| 654 Enqueue(); | 654 Enqueue(); |
| 655 ScheduleDecodeBufferTaskIfNeeded(); | 655 ScheduleDecodeBufferTaskIfNeeded(); |
| 656 } | 656 } |
| 657 } | 657 } |
| 658 } | 658 } |
| 659 | 659 |
| 660 void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_buffer_id) { | 660 void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_buffer_id) { |
| 661 DVLOGF(3) << "picture_buffer_id=" << picture_buffer_id; | 661 DVLOGF(4) << "picture_buffer_id=" << picture_buffer_id; |
| 662 // Must be run on child thread, as we'll insert a sync in the EGL context. | 662 // Must be run on child thread, as we'll insert a sync in the EGL context. |
| 663 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 663 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 664 | 664 |
| 665 std::unique_ptr<EGLSyncKHRRef> egl_sync_ref; | 665 std::unique_ptr<EGLSyncKHRRef> egl_sync_ref; |
| 666 | 666 |
| 667 if (!make_context_current_cb_.is_null()) { | 667 if (!make_context_current_cb_.is_null()) { |
| 668 if (!make_context_current_cb_.Run()) { | 668 if (!make_context_current_cb_.Run()) { |
| 669 LOGF(ERROR) << "could not make context current"; | 669 LOGF(ERROR) << "could not make context current"; |
| 670 NOTIFY_ERROR(PLATFORM_FAILURE); | 670 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 671 return; | 671 return; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 685 egl_sync_ref.reset(new EGLSyncKHRRef(egl_display_, egl_sync)); | 685 egl_sync_ref.reset(new EGLSyncKHRRef(egl_display_, egl_sync)); |
| 686 } | 686 } |
| 687 | 687 |
| 688 decoder_thread_.task_runner()->PostTask( | 688 decoder_thread_.task_runner()->PostTask( |
| 689 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::ReusePictureBufferTask, | 689 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::ReusePictureBufferTask, |
| 690 base::Unretained(this), picture_buffer_id, | 690 base::Unretained(this), picture_buffer_id, |
| 691 base::Passed(&egl_sync_ref))); | 691 base::Passed(&egl_sync_ref))); |
| 692 } | 692 } |
| 693 | 693 |
| 694 void V4L2VideoDecodeAccelerator::Flush() { | 694 void V4L2VideoDecodeAccelerator::Flush() { |
| 695 DVLOGF(3); | 695 DVLOGF(2); |
| 696 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 696 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 697 decoder_thread_.task_runner()->PostTask( | 697 decoder_thread_.task_runner()->PostTask( |
| 698 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::FlushTask, | 698 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::FlushTask, |
| 699 base::Unretained(this))); | 699 base::Unretained(this))); |
| 700 } | 700 } |
| 701 | 701 |
| 702 void V4L2VideoDecodeAccelerator::Reset() { | 702 void V4L2VideoDecodeAccelerator::Reset() { |
| 703 DVLOGF(3); | 703 DVLOGF(2); |
| 704 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 704 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 705 decoder_thread_.task_runner()->PostTask( | 705 decoder_thread_.task_runner()->PostTask( |
| 706 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::ResetTask, | 706 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::ResetTask, |
| 707 base::Unretained(this))); | 707 base::Unretained(this))); |
| 708 } | 708 } |
| 709 | 709 |
| 710 void V4L2VideoDecodeAccelerator::Destroy() { | 710 void V4L2VideoDecodeAccelerator::Destroy() { |
| 711 DVLOGF(3); | 711 DVLOGF(2); |
| 712 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 712 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 713 | 713 |
| 714 // We're destroying; cancel all callbacks. | 714 // We're destroying; cancel all callbacks. |
| 715 client_ptr_factory_.reset(); | 715 client_ptr_factory_.reset(); |
| 716 weak_this_factory_.InvalidateWeakPtrs(); | 716 weak_this_factory_.InvalidateWeakPtrs(); |
| 717 | 717 |
| 718 // If the decoder thread is running, destroy using posted task. | 718 // If the decoder thread is running, destroy using posted task. |
| 719 if (decoder_thread_.IsRunning()) { | 719 if (decoder_thread_.IsRunning()) { |
| 720 decoder_thread_.task_runner()->PostTask( | 720 decoder_thread_.task_runner()->PostTask( |
| 721 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::DestroyTask, | 721 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::DestroyTask, |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 745 scoped_refptr<V4L2Device> device = V4L2Device::Create(); | 745 scoped_refptr<V4L2Device> device = V4L2Device::Create(); |
| 746 if (!device) | 746 if (!device) |
| 747 return SupportedProfiles(); | 747 return SupportedProfiles(); |
| 748 | 748 |
| 749 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), | 749 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), |
| 750 supported_input_fourccs_); | 750 supported_input_fourccs_); |
| 751 } | 751 } |
| 752 | 752 |
| 753 void V4L2VideoDecodeAccelerator::DecodeTask( | 753 void V4L2VideoDecodeAccelerator::DecodeTask( |
| 754 const BitstreamBuffer& bitstream_buffer) { | 754 const BitstreamBuffer& bitstream_buffer) { |
| 755 DVLOGF(3) << "input_id=" << bitstream_buffer.id(); | 755 DVLOGF(4) << "input_id=" << bitstream_buffer.id(); |
| 756 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 756 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 757 DCHECK_NE(decoder_state_, kUninitialized); | 757 DCHECK_NE(decoder_state_, kUninitialized); |
| 758 TRACE_EVENT1("Video Decoder", "V4L2VDA::DecodeTask", "input_id", | 758 TRACE_EVENT1("Video Decoder", "V4L2VDA::DecodeTask", "input_id", |
| 759 bitstream_buffer.id()); | 759 bitstream_buffer.id()); |
| 760 | 760 |
| 761 std::unique_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( | 761 std::unique_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( |
| 762 decode_client_, decode_task_runner_, | 762 decode_client_, decode_task_runner_, |
| 763 std::unique_ptr<SharedMemoryRegion>( | 763 std::unique_ptr<SharedMemoryRegion>( |
| 764 new SharedMemoryRegion(bitstream_buffer, true)), | 764 new SharedMemoryRegion(bitstream_buffer, true)), |
| 765 bitstream_buffer.id())); | 765 bitstream_buffer.id())); |
| 766 | 766 |
| 767 // Skip empty buffer. | 767 // Skip empty buffer. |
| 768 if (bitstream_buffer.size() == 0) | 768 if (bitstream_buffer.size() == 0) |
| 769 return; | 769 return; |
| 770 | 770 |
| 771 if (!bitstream_record->shm->Map()) { | 771 if (!bitstream_record->shm->Map()) { |
| 772 LOGF(ERROR) << "could not map bitstream_buffer"; | 772 LOGF(ERROR) << "could not map bitstream_buffer"; |
| 773 NOTIFY_ERROR(UNREADABLE_INPUT); | 773 NOTIFY_ERROR(UNREADABLE_INPUT); |
| 774 return; | 774 return; |
| 775 } | 775 } |
| 776 DVLOGF(3) << "mapped at=" << bitstream_record->shm->memory(); | 776 DVLOGF(4) << "mapped at=" << bitstream_record->shm->memory(); |
| 777 | 777 |
| 778 if (decoder_state_ == kResetting || decoder_flushing_) { | 778 if (decoder_state_ == kResetting || decoder_flushing_) { |
| 779 // In the case that we're resetting or flushing, we need to delay decoding | 779 // In the case that we're resetting or flushing, we need to delay decoding |
| 780 // the BitstreamBuffers that come after the Reset() or Flush() call. When | 780 // the BitstreamBuffers that come after the Reset() or Flush() call. When |
| 781 // we're here, we know that this DecodeTask() was scheduled by a Decode() | 781 // we're here, we know that this DecodeTask() was scheduled by a Decode() |
| 782 // call that came after (in the client thread) the Reset() or Flush() call; | 782 // call that came after (in the client thread) the Reset() or Flush() call; |
| 783 // thus set up the delay if necessary. | 783 // thus set up the delay if necessary. |
| 784 if (decoder_delay_bitstream_buffer_id_ == -1) | 784 if (decoder_delay_bitstream_buffer_id_ == -1) |
| 785 decoder_delay_bitstream_buffer_id_ = bitstream_record->input_id; | 785 decoder_delay_bitstream_buffer_id_ = bitstream_record->input_id; |
| 786 } else if (decoder_state_ == kError) { | 786 } else if (decoder_state_ == kError) { |
| 787 DVLOGF(2) << "early out: kError state"; | 787 DVLOGF(2) << "early out: kError state"; |
| 788 return; | 788 return; |
| 789 } | 789 } |
| 790 | 790 |
| 791 decoder_input_queue_.push( | 791 decoder_input_queue_.push( |
| 792 linked_ptr<BitstreamBufferRef>(bitstream_record.release())); | 792 linked_ptr<BitstreamBufferRef>(bitstream_record.release())); |
| 793 decoder_decode_buffer_tasks_scheduled_++; | 793 decoder_decode_buffer_tasks_scheduled_++; |
| 794 DecodeBufferTask(); | 794 DecodeBufferTask(); |
| 795 } | 795 } |
| 796 | 796 |
| 797 void V4L2VideoDecodeAccelerator::DecodeBufferTask() { | 797 void V4L2VideoDecodeAccelerator::DecodeBufferTask() { |
| 798 DVLOGF(3); | 798 DVLOGF(4); |
| 799 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 799 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 800 DCHECK_NE(decoder_state_, kUninitialized); | 800 DCHECK_NE(decoder_state_, kUninitialized); |
| 801 TRACE_EVENT0("Video Decoder", "V4L2VDA::DecodeBufferTask"); | 801 TRACE_EVENT0("Video Decoder", "V4L2VDA::DecodeBufferTask"); |
| 802 | 802 |
| 803 decoder_decode_buffer_tasks_scheduled_--; | 803 decoder_decode_buffer_tasks_scheduled_--; |
| 804 | 804 |
| 805 if (decoder_state_ != kInitialized && decoder_state_ != kDecoding) { | 805 if (decoder_state_ != kInitialized && decoder_state_ != kDecoding) { |
| 806 DVLOGF(2) << "early out: state=" << decoder_state_; | 806 DVLOGF(2) << "early out: state=" << decoder_state_; |
| 807 return; | 807 return; |
| 808 } | 808 } |
| 809 | 809 |
| 810 if (decoder_current_bitstream_buffer_ == NULL) { | 810 if (decoder_current_bitstream_buffer_ == NULL) { |
| 811 if (decoder_input_queue_.empty()) { | 811 if (decoder_input_queue_.empty()) { |
| 812 // We're waiting for a new buffer -- exit without scheduling a new task. | 812 // We're waiting for a new buffer -- exit without scheduling a new task. |
| 813 return; | 813 return; |
| 814 } | 814 } |
| 815 linked_ptr<BitstreamBufferRef>& buffer_ref = decoder_input_queue_.front(); | 815 linked_ptr<BitstreamBufferRef>& buffer_ref = decoder_input_queue_.front(); |
| 816 if (decoder_delay_bitstream_buffer_id_ == buffer_ref->input_id) { | 816 if (decoder_delay_bitstream_buffer_id_ == buffer_ref->input_id) { |
| 817 // We're asked to delay decoding on this and subsequent buffers. | 817 // We're asked to delay decoding on this and subsequent buffers. |
| 818 return; | 818 return; |
| 819 } | 819 } |
| 820 | 820 |
| 821 // Setup to use the next buffer. | 821 // Setup to use the next buffer. |
| 822 decoder_current_bitstream_buffer_.reset(buffer_ref.release()); | 822 decoder_current_bitstream_buffer_.reset(buffer_ref.release()); |
| 823 decoder_input_queue_.pop(); | 823 decoder_input_queue_.pop(); |
| 824 const auto& shm = decoder_current_bitstream_buffer_->shm; | 824 const auto& shm = decoder_current_bitstream_buffer_->shm; |
| 825 if (shm) { | 825 if (shm) { |
| 826 DVLOGF(3) << "reading input_id=" | 826 DVLOGF(4) << "reading input_id=" |
| 827 << decoder_current_bitstream_buffer_->input_id | 827 << decoder_current_bitstream_buffer_->input_id |
| 828 << ", addr=" << shm->memory() << ", size=" << shm->size(); | 828 << ", addr=" << shm->memory() << ", size=" << shm->size(); |
| 829 } else { | 829 } else { |
| 830 DCHECK_EQ(decoder_current_bitstream_buffer_->input_id, kFlushBufferId); | 830 DCHECK_EQ(decoder_current_bitstream_buffer_->input_id, kFlushBufferId); |
| 831 DVLOGF(3) << "reading input_id=kFlushBufferId"; | 831 DVLOGF(4) << "reading input_id=kFlushBufferId"; |
| 832 } | 832 } |
| 833 } | 833 } |
| 834 bool schedule_task = false; | 834 bool schedule_task = false; |
| 835 size_t decoded_size = 0; | 835 size_t decoded_size = 0; |
| 836 const auto& shm = decoder_current_bitstream_buffer_->shm; | 836 const auto& shm = decoder_current_bitstream_buffer_->shm; |
| 837 if (!shm) { | 837 if (!shm) { |
| 838 // This is a dummy buffer, queued to flush the pipe. Flush. | 838 // This is a dummy buffer, queued to flush the pipe. Flush. |
| 839 DCHECK_EQ(decoder_current_bitstream_buffer_->input_id, kFlushBufferId); | 839 DCHECK_EQ(decoder_current_bitstream_buffer_->input_id, kFlushBufferId); |
| 840 // Enqueue a buffer guaranteed to be empty. To do that, we flush the | 840 // Enqueue a buffer guaranteed to be empty. To do that, we flush the |
| 841 // current input, enqueue no data to the next frame, then flush that down. | 841 // current input, enqueue no data to the next frame, then flush that down. |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 890 // Failed during decode. | 890 // Failed during decode. |
| 891 return; | 891 return; |
| 892 } | 892 } |
| 893 | 893 |
| 894 if (schedule_task) { | 894 if (schedule_task) { |
| 895 decoder_current_bitstream_buffer_->bytes_used += decoded_size; | 895 decoder_current_bitstream_buffer_->bytes_used += decoded_size; |
| 896 if ((shm ? shm->size() : 0) == | 896 if ((shm ? shm->size() : 0) == |
| 897 decoder_current_bitstream_buffer_->bytes_used) { | 897 decoder_current_bitstream_buffer_->bytes_used) { |
| 898 // Our current bitstream buffer is done; return it. | 898 // Our current bitstream buffer is done; return it. |
| 899 int32_t input_id = decoder_current_bitstream_buffer_->input_id; | 899 int32_t input_id = decoder_current_bitstream_buffer_->input_id; |
| 900 DVLOGF(3) << "finished input_id=" << input_id; | 900 DVLOGF(4) << "finished input_id=" << input_id; |
| 901 // BitstreamBufferRef destructor calls NotifyEndOfBitstreamBuffer(). | 901 // BitstreamBufferRef destructor calls NotifyEndOfBitstreamBuffer(). |
| 902 decoder_current_bitstream_buffer_.reset(); | 902 decoder_current_bitstream_buffer_.reset(); |
| 903 } | 903 } |
| 904 ScheduleDecodeBufferTaskIfNeeded(); | 904 ScheduleDecodeBufferTaskIfNeeded(); |
| 905 } | 905 } |
| 906 } | 906 } |
| 907 | 907 |
| 908 bool V4L2VideoDecodeAccelerator::AdvanceFrameFragment(const uint8_t* data, | 908 bool V4L2VideoDecodeAccelerator::AdvanceFrameFragment(const uint8_t* data, |
| 909 size_t size, | 909 size_t size, |
| 910 size_t* endpos) { | 910 size_t* endpos) { |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1002 decoder_decode_buffer_tasks_scheduled_++; | 1002 decoder_decode_buffer_tasks_scheduled_++; |
| 1003 decoder_thread_.task_runner()->PostTask( | 1003 decoder_thread_.task_runner()->PostTask( |
| 1004 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::DecodeBufferTask, | 1004 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::DecodeBufferTask, |
| 1005 base::Unretained(this))); | 1005 base::Unretained(this))); |
| 1006 } | 1006 } |
| 1007 } | 1007 } |
| 1008 | 1008 |
| 1009 bool V4L2VideoDecodeAccelerator::DecodeBufferInitial(const void* data, | 1009 bool V4L2VideoDecodeAccelerator::DecodeBufferInitial(const void* data, |
| 1010 size_t size, | 1010 size_t size, |
| 1011 size_t* endpos) { | 1011 size_t* endpos) { |
| 1012 DVLOGF(3) << "data=" << data << ", size=" << size; | 1012 DVLOGF(4) << "data=" << data << ", size=" << size; |
| 1013 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1013 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 1014 DCHECK_EQ(decoder_state_, kInitialized); | 1014 DCHECK_EQ(decoder_state_, kInitialized); |
| 1015 // Initial decode. We haven't been able to get output stream format info yet. | 1015 // Initial decode. We haven't been able to get output stream format info yet. |
| 1016 // Get it, and start decoding. | 1016 // Get it, and start decoding. |
| 1017 | 1017 |
| 1018 // Copy in and send to HW. | 1018 // Copy in and send to HW. |
| 1019 if (!AppendToInputFrame(data, size)) | 1019 if (!AppendToInputFrame(data, size)) |
| 1020 return false; | 1020 return false; |
| 1021 | 1021 |
| 1022 // If we only have a partial frame, don't flush and process yet. | 1022 // If we only have a partial frame, don't flush and process yet. |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1038 | 1038 |
| 1039 *endpos = size; | 1039 *endpos = size; |
| 1040 | 1040 |
| 1041 if (again) { | 1041 if (again) { |
| 1042 // Need more stream to decode format, return true and schedule next buffer. | 1042 // Need more stream to decode format, return true and schedule next buffer. |
| 1043 return true; | 1043 return true; |
| 1044 } | 1044 } |
| 1045 | 1045 |
| 1046 // Run this initialization only on first startup. | 1046 // Run this initialization only on first startup. |
| 1047 if (output_buffer_map_.empty()) { | 1047 if (output_buffer_map_.empty()) { |
| 1048 DVLOGF(3) << "running initialization"; | 1048 DVLOGF(4) << "running initialization"; |
| 1049 // Success! Setup our parameters. | 1049 // Success! Setup our parameters. |
| 1050 if (!CreateBuffersForFormat(format, visible_size)) | 1050 if (!CreateBuffersForFormat(format, visible_size)) |
| 1051 return false; | 1051 return false; |
| 1052 // We are waiting for AssignPictureBuffers. Do not set the state to | 1052 // We are waiting for AssignPictureBuffers. Do not set the state to |
| 1053 // kDecoding. | 1053 // kDecoding. |
| 1054 } else { | 1054 } else { |
| 1055 decoder_state_ = kDecoding; | 1055 decoder_state_ = kDecoding; |
| 1056 ScheduleDecodeBufferTaskIfNeeded(); | 1056 ScheduleDecodeBufferTaskIfNeeded(); |
| 1057 } | 1057 } |
| 1058 return true; | 1058 return true; |
| 1059 } | 1059 } |
| 1060 | 1060 |
| 1061 bool V4L2VideoDecodeAccelerator::DecodeBufferContinue(const void* data, | 1061 bool V4L2VideoDecodeAccelerator::DecodeBufferContinue(const void* data, |
| 1062 size_t size) { | 1062 size_t size) { |
| 1063 DVLOGF(3) << "data=" << data << ", size=" << size; | 1063 DVLOGF(4) << "data=" << data << ", size=" << size; |
| 1064 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1064 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 1065 DCHECK_EQ(decoder_state_, kDecoding); | 1065 DCHECK_EQ(decoder_state_, kDecoding); |
| 1066 | 1066 |
| 1067 // Both of these calls will set kError state if they fail. | 1067 // Both of these calls will set kError state if they fail. |
| 1068 // Only flush the frame if it's complete. | 1068 // Only flush the frame if it's complete. |
| 1069 return (AppendToInputFrame(data, size) && | 1069 return (AppendToInputFrame(data, size) && |
| 1070 (decoder_partial_frame_pending_ || FlushInputFrame())); | 1070 (decoder_partial_frame_pending_ || FlushInputFrame())); |
| 1071 } | 1071 } |
| 1072 | 1072 |
| 1073 bool V4L2VideoDecodeAccelerator::AppendToInputFrame(const void* data, | 1073 bool V4L2VideoDecodeAccelerator::AppendToInputFrame(const void* data, |
| 1074 size_t size) { | 1074 size_t size) { |
| 1075 DVLOGF(3); | 1075 DVLOGF(3); |
|
Pawel Osciak
2017/05/23 09:49:22
4?
Owen Lin
2017/06/02 08:51:43
Done.
| |
| 1076 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1076 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 1077 DCHECK_NE(decoder_state_, kUninitialized); | 1077 DCHECK_NE(decoder_state_, kUninitialized); |
| 1078 DCHECK_NE(decoder_state_, kResetting); | 1078 DCHECK_NE(decoder_state_, kResetting); |
| 1079 DCHECK_NE(decoder_state_, kError); | 1079 DCHECK_NE(decoder_state_, kError); |
| 1080 // This routine can handle data == NULL and size == 0, which occurs when | 1080 // This routine can handle data == NULL and size == 0, which occurs when |
| 1081 // we queue an empty buffer for the purposes of flushing the pipe. | 1081 // we queue an empty buffer for the purposes of flushing the pipe. |
| 1082 | 1082 |
| 1083 // Flush if we're too big | 1083 // Flush if we're too big |
| 1084 if (decoder_current_input_buffer_ != -1) { | 1084 if (decoder_current_input_buffer_ != -1) { |
| 1085 InputRecord& input_record = | 1085 InputRecord& input_record = |
| 1086 input_buffer_map_[decoder_current_input_buffer_]; | 1086 input_buffer_map_[decoder_current_input_buffer_]; |
| 1087 if (input_record.bytes_used + size > input_record.length) { | 1087 if (input_record.bytes_used + size > input_record.length) { |
| 1088 if (!FlushInputFrame()) | 1088 if (!FlushInputFrame()) |
| 1089 return false; | 1089 return false; |
| 1090 decoder_current_input_buffer_ = -1; | 1090 decoder_current_input_buffer_ = -1; |
| 1091 } | 1091 } |
| 1092 } | 1092 } |
| 1093 | 1093 |
| 1094 // Try to get an available input buffer | 1094 // Try to get an available input buffer |
| 1095 if (decoder_current_input_buffer_ == -1) { | 1095 if (decoder_current_input_buffer_ == -1) { |
| 1096 if (free_input_buffers_.empty()) { | 1096 if (free_input_buffers_.empty()) { |
| 1097 // See if we can get more free buffers from HW | 1097 // See if we can get more free buffers from HW |
| 1098 Dequeue(); | 1098 Dequeue(); |
| 1099 if (free_input_buffers_.empty()) { | 1099 if (free_input_buffers_.empty()) { |
| 1100 // Nope! | 1100 // Nope! |
| 1101 DVLOGF(2) << "stalled for input buffers"; | 1101 DVLOGF(2) << "stalled for input buffers"; |
|
Pawel Osciak
2017/05/23 09:49:21
3, this is a very frequent print that doesn't give
Owen Lin
2017/06/02 08:51:44
Thanks.
| |
| 1102 return false; | 1102 return false; |
| 1103 } | 1103 } |
| 1104 } | 1104 } |
| 1105 decoder_current_input_buffer_ = free_input_buffers_.back(); | 1105 decoder_current_input_buffer_ = free_input_buffers_.back(); |
| 1106 free_input_buffers_.pop_back(); | 1106 free_input_buffers_.pop_back(); |
| 1107 InputRecord& input_record = | 1107 InputRecord& input_record = |
| 1108 input_buffer_map_[decoder_current_input_buffer_]; | 1108 input_buffer_map_[decoder_current_input_buffer_]; |
| 1109 DCHECK_EQ(input_record.bytes_used, 0); | 1109 DCHECK_EQ(input_record.bytes_used, 0); |
| 1110 DCHECK_EQ(input_record.input_id, -1); | 1110 DCHECK_EQ(input_record.input_id, -1); |
| 1111 DCHECK(decoder_current_bitstream_buffer_ != NULL); | 1111 DCHECK(decoder_current_bitstream_buffer_ != NULL); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1129 } | 1129 } |
| 1130 memcpy(reinterpret_cast<uint8_t*>(input_record.address) + | 1130 memcpy(reinterpret_cast<uint8_t*>(input_record.address) + |
| 1131 input_record.bytes_used, | 1131 input_record.bytes_used, |
| 1132 data, size); | 1132 data, size); |
| 1133 input_record.bytes_used += size; | 1133 input_record.bytes_used += size; |
| 1134 | 1134 |
| 1135 return true; | 1135 return true; |
| 1136 } | 1136 } |
| 1137 | 1137 |
| 1138 bool V4L2VideoDecodeAccelerator::FlushInputFrame() { | 1138 bool V4L2VideoDecodeAccelerator::FlushInputFrame() { |
| 1139 DVLOGF(3); | 1139 DVLOGF(2); |
|
Pawel Osciak
2017/05/23 09:49:22
I think this is actually a part of each frame task
Owen Lin
2017/06/02 08:51:44
Ah, Right. I was confused with Flush. It is not ab
| |
| 1140 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1140 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 1141 DCHECK_NE(decoder_state_, kUninitialized); | 1141 DCHECK_NE(decoder_state_, kUninitialized); |
| 1142 DCHECK_NE(decoder_state_, kResetting); | 1142 DCHECK_NE(decoder_state_, kResetting); |
| 1143 DCHECK_NE(decoder_state_, kError); | 1143 DCHECK_NE(decoder_state_, kError); |
| 1144 | 1144 |
| 1145 if (decoder_current_input_buffer_ == -1) | 1145 if (decoder_current_input_buffer_ == -1) |
| 1146 return true; | 1146 return true; |
| 1147 | 1147 |
| 1148 InputRecord& input_record = input_buffer_map_[decoder_current_input_buffer_]; | 1148 InputRecord& input_record = input_buffer_map_[decoder_current_input_buffer_]; |
| 1149 DCHECK_NE(input_record.input_id, -1); | 1149 DCHECK_NE(input_record.input_id, -1); |
| 1150 DCHECK(input_record.input_id != kFlushBufferId || | 1150 DCHECK(input_record.input_id != kFlushBufferId || |
| 1151 input_record.bytes_used == 0); | 1151 input_record.bytes_used == 0); |
| 1152 // * if input_id >= 0, this input buffer was prompted by a bitstream buffer we | 1152 // * if input_id >= 0, this input buffer was prompted by a bitstream buffer we |
| 1153 // got from the client. We can skip it if it is empty. | 1153 // got from the client. We can skip it if it is empty. |
| 1154 // * if input_id < 0 (should be kFlushBufferId in this case), this input | 1154 // * if input_id < 0 (should be kFlushBufferId in this case), this input |
| 1155 // buffer was prompted by a flush buffer, and should be queued even when | 1155 // buffer was prompted by a flush buffer, and should be queued even when |
| 1156 // empty. | 1156 // empty. |
| 1157 if (input_record.input_id >= 0 && input_record.bytes_used == 0) { | 1157 if (input_record.input_id >= 0 && input_record.bytes_used == 0) { |
| 1158 input_record.input_id = -1; | 1158 input_record.input_id = -1; |
| 1159 free_input_buffers_.push_back(decoder_current_input_buffer_); | 1159 free_input_buffers_.push_back(decoder_current_input_buffer_); |
| 1160 decoder_current_input_buffer_ = -1; | 1160 decoder_current_input_buffer_ = -1; |
| 1161 return true; | 1161 return true; |
| 1162 } | 1162 } |
| 1163 | 1163 |
| 1164 // Queue it. | 1164 // Queue it. |
| 1165 input_ready_queue_.push(decoder_current_input_buffer_); | 1165 input_ready_queue_.push(decoder_current_input_buffer_); |
| 1166 decoder_current_input_buffer_ = -1; | 1166 decoder_current_input_buffer_ = -1; |
| 1167 DVLOGF(3) << "submitting input_id=" << input_record.input_id; | 1167 DVLOGF(2) << "submitting input_id=" << input_record.input_id; |
|
Pawel Osciak
2017/05/23 09:49:21
Ditto.
Owen Lin
2017/06/02 08:51:43
Done.
| |
| 1168 // Enqueue once since there's new available input for it. | 1168 // Enqueue once since there's new available input for it. |
| 1169 Enqueue(); | 1169 Enqueue(); |
| 1170 | 1170 |
| 1171 return (decoder_state_ != kError); | 1171 return (decoder_state_ != kError); |
| 1172 } | 1172 } |
| 1173 | 1173 |
| 1174 void V4L2VideoDecodeAccelerator::ServiceDeviceTask(bool event_pending) { | 1174 void V4L2VideoDecodeAccelerator::ServiceDeviceTask(bool event_pending) { |
| 1175 DVLOGF(3); | 1175 DVLOGF(3); |
| 1176 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1176 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 1177 DCHECK_NE(decoder_state_, kUninitialized); | 1177 DCHECK_NE(decoder_state_, kUninitialized); |
| 1178 TRACE_EVENT0("Video Decoder", "V4L2VDA::ServiceDeviceTask"); | 1178 TRACE_EVENT0("Video Decoder", "V4L2VDA::ServiceDeviceTask"); |
| 1179 | 1179 |
| 1180 if (decoder_state_ == kResetting) { | 1180 if (decoder_state_ == kResetting) { |
| 1181 DVLOGF(2) << "early out: kResetting state"; | 1181 DVLOGF(3) << "early out: kResetting state"; |
| 1182 return; | 1182 return; |
| 1183 } else if (decoder_state_ == kError) { | 1183 } else if (decoder_state_ == kError) { |
| 1184 DVLOGF(2) << "early out: kError state"; | 1184 DVLOGF(3) << "early out: kError state"; |
| 1185 return; | 1185 return; |
| 1186 } else if (decoder_state_ == kChangingResolution) { | 1186 } else if (decoder_state_ == kChangingResolution) { |
| 1187 DVLOGF(2) << "early out: kChangingResolution state"; | 1187 DVLOGF(3) << "early out: kChangingResolution state"; |
| 1188 return; | 1188 return; |
| 1189 } | 1189 } |
| 1190 | 1190 |
| 1191 bool resolution_change_pending = false; | 1191 bool resolution_change_pending = false; |
| 1192 if (event_pending) | 1192 if (event_pending) |
| 1193 resolution_change_pending = DequeueResolutionChangeEvent(); | 1193 resolution_change_pending = DequeueResolutionChangeEvent(); |
| 1194 Dequeue(); | 1194 Dequeue(); |
| 1195 Enqueue(); | 1195 Enqueue(); |
| 1196 | 1196 |
| 1197 // Clear the interrupt fd. | 1197 // Clear the interrupt fd. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1211 // * device_poll_thread_ is running normally | 1211 // * device_poll_thread_ is running normally |
| 1212 // * device_poll_thread_ scheduled us, but then a ResetTask() or DestroyTask() | 1212 // * device_poll_thread_ scheduled us, but then a ResetTask() or DestroyTask() |
| 1213 // shut it down, in which case we're either in kResetting or kError states | 1213 // shut it down, in which case we're either in kResetting or kError states |
| 1214 // respectively, and we should have early-outed already. | 1214 // respectively, and we should have early-outed already. |
| 1215 DCHECK(device_poll_thread_.message_loop()); | 1215 DCHECK(device_poll_thread_.message_loop()); |
| 1216 // Queue the DevicePollTask() now. | 1216 // Queue the DevicePollTask() now. |
| 1217 device_poll_thread_.task_runner()->PostTask( | 1217 device_poll_thread_.task_runner()->PostTask( |
| 1218 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::DevicePollTask, | 1218 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::DevicePollTask, |
| 1219 base::Unretained(this), poll_device)); | 1219 base::Unretained(this), poll_device)); |
| 1220 | 1220 |
| 1221 DVLOG(1) << "ServiceDeviceTask(): buffer counts: DEC[" | 1221 DVLOG(3) << "ServiceDeviceTask(): buffer counts: DEC[" |
|
Pawel Osciak
2017/05/23 09:49:21
This is per frame, but actually quite useful at 3
Owen Lin
2017/06/02 08:51:43
Done.
| |
| 1222 << decoder_input_queue_.size() << "->" | 1222 << decoder_input_queue_.size() << "->" << input_ready_queue_.size() |
|
Pawel Osciak
2017/05/23 09:49:21
Could we keep the original formatting please, I fe
Owen Lin
2017/06/02 08:51:43
OK. But it is the result of "git cl format", we wi
Pawel Osciak
2017/06/08 03:57:11
Yes, unfortunately.
| |
| 1223 << input_ready_queue_.size() << "] => DEVICE[" | 1223 << "] => DEVICE[" << free_input_buffers_.size() << "+" |
| 1224 << free_input_buffers_.size() << "+" | 1224 << input_buffer_queued_count_ << "/" << input_buffer_map_.size() |
| 1225 << input_buffer_queued_count_ << "/" | 1225 << "->" << free_output_buffers_.size() << "+" |
| 1226 << input_buffer_map_.size() << "->" | 1226 << output_buffer_queued_count_ << "/" << output_buffer_map_.size() |
| 1227 << free_output_buffers_.size() << "+" | 1227 << "] => PROCESSOR[" << image_processor_bitstream_buffer_ids_.size() |
| 1228 << output_buffer_queued_count_ << "/" | 1228 << "] => CLIENT[" << decoder_frames_at_client_ << "]"; |
| 1229 << output_buffer_map_.size() << "] => PROCESSOR[" | |
| 1230 << image_processor_bitstream_buffer_ids_.size() << "] => CLIENT[" | |
| 1231 << decoder_frames_at_client_ << "]"; | |
| 1232 | 1229 |
| 1233 ScheduleDecodeBufferTaskIfNeeded(); | 1230 ScheduleDecodeBufferTaskIfNeeded(); |
| 1234 if (resolution_change_pending) | 1231 if (resolution_change_pending) |
| 1235 StartResolutionChange(); | 1232 StartResolutionChange(); |
| 1236 } | 1233 } |
| 1237 | 1234 |
| 1238 void V4L2VideoDecodeAccelerator::Enqueue() { | 1235 void V4L2VideoDecodeAccelerator::Enqueue() { |
| 1239 DVLOGF(3); | 1236 DVLOGF(3); |
|
Pawel Osciak
2017/05/23 09:49:21
4?
Owen Lin
2017/06/02 08:51:43
Done.
| |
| 1240 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1237 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 1241 DCHECK_NE(decoder_state_, kUninitialized); | 1238 DCHECK_NE(decoder_state_, kUninitialized); |
| 1242 TRACE_EVENT0("Video Decoder", "V4L2VDA::Enqueue"); | 1239 TRACE_EVENT0("Video Decoder", "V4L2VDA::Enqueue"); |
| 1243 | 1240 |
| 1244 // Drain the pipe of completed decode buffers. | 1241 // Drain the pipe of completed decode buffers. |
| 1245 const int old_inputs_queued = input_buffer_queued_count_; | 1242 const int old_inputs_queued = input_buffer_queued_count_; |
| 1246 while (!input_ready_queue_.empty()) { | 1243 while (!input_ready_queue_.empty()) { |
| 1247 const int buffer = input_ready_queue_.front(); | 1244 const int buffer = input_ready_queue_.front(); |
| 1248 InputRecord& input_record = input_buffer_map_[buffer]; | 1245 InputRecord& input_record = input_buffer_map_[buffer]; |
| 1249 if (input_record.input_id == kFlushBufferId && decoder_cmd_supported_) { | 1246 if (input_record.input_id == kFlushBufferId && decoder_cmd_supported_) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1304 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1301 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1305 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type); | 1302 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type); |
| 1306 output_streamon_ = true; | 1303 output_streamon_ = true; |
| 1307 } | 1304 } |
| 1308 } | 1305 } |
| 1309 } | 1306 } |
| 1310 | 1307 |
| 1311 bool V4L2VideoDecodeAccelerator::DequeueResolutionChangeEvent() { | 1308 bool V4L2VideoDecodeAccelerator::DequeueResolutionChangeEvent() { |
| 1312 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1309 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 1313 DCHECK_NE(decoder_state_, kUninitialized); | 1310 DCHECK_NE(decoder_state_, kUninitialized); |
| 1314 DVLOGF(3); | 1311 DVLOGF(3); |
|
Pawel Osciak
2017/05/23 09:49:21
2?
Owen Lin
2017/06/02 08:51:44
Done.
| |
| 1315 | 1312 |
| 1316 struct v4l2_event ev; | 1313 struct v4l2_event ev; |
| 1317 memset(&ev, 0, sizeof(ev)); | 1314 memset(&ev, 0, sizeof(ev)); |
| 1318 | 1315 |
| 1319 while (device_->Ioctl(VIDIOC_DQEVENT, &ev) == 0) { | 1316 while (device_->Ioctl(VIDIOC_DQEVENT, &ev) == 0) { |
| 1320 if (ev.type == V4L2_EVENT_SOURCE_CHANGE) { | 1317 if (ev.type == V4L2_EVENT_SOURCE_CHANGE) { |
| 1321 if (ev.u.src_change.changes & V4L2_EVENT_SRC_CH_RESOLUTION) { | 1318 if (ev.u.src_change.changes & V4L2_EVENT_SRC_CH_RESOLUTION) { |
| 1322 DVLOGF(3) << "got resolution change event."; | 1319 DVLOGF(3) << "got resolution change event."; |
|
Pawel Osciak
2017/05/23 09:49:21
2?
Owen Lin
2017/06/02 08:51:43
Done.
| |
| 1323 return true; | 1320 return true; |
| 1324 } | 1321 } |
| 1325 } else { | 1322 } else { |
| 1326 LOGF(ERROR) << "got an event (" << ev.type | 1323 LOGF(ERROR) << "got an event (" << ev.type |
| 1327 << ") we haven't subscribed to."; | 1324 << ") we haven't subscribed to."; |
| 1328 } | 1325 } |
| 1329 } | 1326 } |
| 1330 return false; | 1327 return false; |
| 1331 } | 1328 } |
| 1332 | 1329 |
| 1333 void V4L2VideoDecodeAccelerator::Dequeue() { | 1330 void V4L2VideoDecodeAccelerator::Dequeue() { |
| 1334 DVLOGF(3); | 1331 DVLOGF(3); |
|
Pawel Osciak
2017/05/23 09:49:21
Perhaps 4?
Owen Lin
2017/06/02 08:51:43
Done.
| |
| 1335 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1332 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 1336 DCHECK_NE(decoder_state_, kUninitialized); | 1333 DCHECK_NE(decoder_state_, kUninitialized); |
| 1337 TRACE_EVENT0("Video Decoder", "V4L2VDA::Dequeue"); | 1334 TRACE_EVENT0("Video Decoder", "V4L2VDA::Dequeue"); |
| 1338 | 1335 |
| 1339 while (input_buffer_queued_count_ > 0) { | 1336 while (input_buffer_queued_count_ > 0) { |
| 1340 if (!DequeueInputBuffer()) | 1337 if (!DequeueInputBuffer()) |
| 1341 break; | 1338 break; |
| 1342 } | 1339 } |
| 1343 while (output_buffer_queued_count_ > 0) { | 1340 while (output_buffer_queued_count_ > 0) { |
| 1344 if (!DequeueOutputBuffer()) | 1341 if (!DequeueOutputBuffer()) |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1414 DCHECK_EQ(output_record.state, kAtDevice); | 1411 DCHECK_EQ(output_record.state, kAtDevice); |
| 1415 DCHECK_NE(output_record.picture_id, -1); | 1412 DCHECK_NE(output_record.picture_id, -1); |
| 1416 output_buffer_queued_count_--; | 1413 output_buffer_queued_count_--; |
| 1417 if (dqbuf.m.planes[0].bytesused == 0) { | 1414 if (dqbuf.m.planes[0].bytesused == 0) { |
| 1418 // This is an empty output buffer returned as part of a flush. | 1415 // This is an empty output buffer returned as part of a flush. |
| 1419 output_record.state = kFree; | 1416 output_record.state = kFree; |
| 1420 free_output_buffers_.push_back(dqbuf.index); | 1417 free_output_buffers_.push_back(dqbuf.index); |
| 1421 } else { | 1418 } else { |
| 1422 int32_t bitstream_buffer_id = dqbuf.timestamp.tv_sec; | 1419 int32_t bitstream_buffer_id = dqbuf.timestamp.tv_sec; |
| 1423 DCHECK_GE(bitstream_buffer_id, 0); | 1420 DCHECK_GE(bitstream_buffer_id, 0); |
| 1424 DVLOGF(3) << "Dequeue output buffer: dqbuf index=" << dqbuf.index | 1421 DVLOGF(3) << "Dequeue output buffer: dqbuf index=" << dqbuf.index |
|
Pawel Osciak
2017/05/23 09:49:22
Perhaps 4?
Owen Lin
2017/06/02 08:51:43
Done.
| |
| 1425 << " bitstream input_id=" << bitstream_buffer_id; | 1422 << " bitstream input_id=" << bitstream_buffer_id; |
| 1426 if (image_processor_device_) { | 1423 if (image_processor_device_) { |
| 1427 if (!ProcessFrame(bitstream_buffer_id, dqbuf.index)) { | 1424 if (!ProcessFrame(bitstream_buffer_id, dqbuf.index)) { |
| 1428 DLOGF(ERROR) << "Processing frame failed"; | 1425 DLOGF(ERROR) << "Processing frame failed"; |
| 1429 NOTIFY_ERROR(PLATFORM_FAILURE); | 1426 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1430 return false; | 1427 return false; |
| 1431 } | 1428 } |
| 1432 } else { | 1429 } else { |
| 1433 output_record.state = kAtClient; | 1430 output_record.state = kAtClient; |
| 1434 decoder_frames_at_client_++; | 1431 decoder_frames_at_client_++; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 1449 struct v4l2_decoder_cmd cmd; | 1446 struct v4l2_decoder_cmd cmd; |
| 1450 memset(&cmd, 0, sizeof(cmd)); | 1447 memset(&cmd, 0, sizeof(cmd)); |
| 1451 cmd.cmd = V4L2_DEC_CMD_START; | 1448 cmd.cmd = V4L2_DEC_CMD_START; |
| 1452 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_DECODER_CMD, &cmd); | 1449 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_DECODER_CMD, &cmd); |
| 1453 } | 1450 } |
| 1454 } | 1451 } |
| 1455 return true; | 1452 return true; |
| 1456 } | 1453 } |
| 1457 | 1454 |
| 1458 bool V4L2VideoDecodeAccelerator::EnqueueInputRecord() { | 1455 bool V4L2VideoDecodeAccelerator::EnqueueInputRecord() { |
| 1459 DVLOGF(3); | 1456 DVLOGF(3); |
|
Pawel Osciak
2017/05/23 09:49:22
Perhaps 4?
Owen Lin
2017/06/02 08:51:43
Done.
| |
| 1460 DCHECK(!input_ready_queue_.empty()); | 1457 DCHECK(!input_ready_queue_.empty()); |
| 1461 | 1458 |
| 1462 // Enqueue an input (VIDEO_OUTPUT) buffer. | 1459 // Enqueue an input (VIDEO_OUTPUT) buffer. |
| 1463 const int buffer = input_ready_queue_.front(); | 1460 const int buffer = input_ready_queue_.front(); |
| 1464 InputRecord& input_record = input_buffer_map_[buffer]; | 1461 InputRecord& input_record = input_buffer_map_[buffer]; |
| 1465 DCHECK(!input_record.at_device); | 1462 DCHECK(!input_record.at_device); |
| 1466 struct v4l2_buffer qbuf; | 1463 struct v4l2_buffer qbuf; |
| 1467 struct v4l2_plane qbuf_plane; | 1464 struct v4l2_plane qbuf_plane; |
| 1468 memset(&qbuf, 0, sizeof(qbuf)); | 1465 memset(&qbuf, 0, sizeof(qbuf)); |
| 1469 memset(&qbuf_plane, 0, sizeof(qbuf_plane)); | 1466 memset(&qbuf_plane, 0, sizeof(qbuf_plane)); |
| 1470 qbuf.index = buffer; | 1467 qbuf.index = buffer; |
| 1471 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1468 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 1472 qbuf.timestamp.tv_sec = input_record.input_id; | 1469 qbuf.timestamp.tv_sec = input_record.input_id; |
| 1473 qbuf.memory = V4L2_MEMORY_MMAP; | 1470 qbuf.memory = V4L2_MEMORY_MMAP; |
| 1474 qbuf.m.planes = &qbuf_plane; | 1471 qbuf.m.planes = &qbuf_plane; |
| 1475 qbuf.m.planes[0].bytesused = input_record.bytes_used; | 1472 qbuf.m.planes[0].bytesused = input_record.bytes_used; |
| 1476 qbuf.length = 1; | 1473 qbuf.length = 1; |
| 1477 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf); | 1474 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf); |
| 1478 input_ready_queue_.pop(); | 1475 input_ready_queue_.pop(); |
| 1479 input_record.at_device = true; | 1476 input_record.at_device = true; |
| 1480 input_buffer_queued_count_++; | 1477 input_buffer_queued_count_++; |
| 1481 DVLOGF(3) << "enqueued input_id=" << input_record.input_id | 1478 DVLOGF(3) << "enqueued input_id=" << input_record.input_id |
|
Pawel Osciak
2017/05/23 09:49:21
Perhaps 4?
Owen Lin
2017/06/02 08:51:43
Done.
| |
| 1482 << " size=" << input_record.bytes_used; | 1479 << " size=" << input_record.bytes_used; |
| 1483 return true; | 1480 return true; |
| 1484 } | 1481 } |
| 1485 | 1482 |
| 1486 bool V4L2VideoDecodeAccelerator::EnqueueOutputRecord() { | 1483 bool V4L2VideoDecodeAccelerator::EnqueueOutputRecord() { |
| 1487 DCHECK(!free_output_buffers_.empty()); | 1484 DCHECK(!free_output_buffers_.empty()); |
| 1488 | 1485 |
| 1489 // Enqueue an output (VIDEO_CAPTURE) buffer. | 1486 // Enqueue an output (VIDEO_CAPTURE) buffer. |
| 1490 const int buffer = free_output_buffers_.front(); | 1487 const int buffer = free_output_buffers_.front(); |
| 1491 DVLOGF(3) << "buffer " << buffer; | 1488 DVLOGF(3) << "buffer " << buffer; |
|
Pawel Osciak
2017/05/23 09:49:21
Perhaps 4?
Owen Lin
2017/06/02 08:51:43
Done.
| |
| 1492 OutputRecord& output_record = output_buffer_map_[buffer]; | 1489 OutputRecord& output_record = output_buffer_map_[buffer]; |
| 1493 DCHECK_EQ(output_record.state, kFree); | 1490 DCHECK_EQ(output_record.state, kFree); |
| 1494 DCHECK_NE(output_record.picture_id, -1); | 1491 DCHECK_NE(output_record.picture_id, -1); |
| 1495 if (output_record.egl_sync != EGL_NO_SYNC_KHR) { | 1492 if (output_record.egl_sync != EGL_NO_SYNC_KHR) { |
| 1496 TRACE_EVENT0("Video Decoder", | 1493 TRACE_EVENT0("Video Decoder", |
| 1497 "V4L2VDA::EnqueueOutputRecord: eglClientWaitSyncKHR"); | 1494 "V4L2VDA::EnqueueOutputRecord: eglClientWaitSyncKHR"); |
| 1498 // If we have to wait for completion, wait. Note that | 1495 // If we have to wait for completion, wait. Note that |
| 1499 // free_output_buffers_ is a FIFO queue, so we always wait on the | 1496 // free_output_buffers_ is a FIFO queue, so we always wait on the |
| 1500 // buffer that has been in the queue the longest. | 1497 // buffer that has been in the queue the longest. |
| 1501 if (eglClientWaitSyncKHR(egl_display_, output_record.egl_sync, 0, | 1498 if (eglClientWaitSyncKHR(egl_display_, output_record.egl_sync, 0, |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1514 std::unique_ptr<struct v4l2_plane[]> qbuf_planes( | 1511 std::unique_ptr<struct v4l2_plane[]> qbuf_planes( |
| 1515 new v4l2_plane[output_planes_count_]); | 1512 new v4l2_plane[output_planes_count_]); |
| 1516 memset(&qbuf, 0, sizeof(qbuf)); | 1513 memset(&qbuf, 0, sizeof(qbuf)); |
| 1517 memset(qbuf_planes.get(), 0, | 1514 memset(qbuf_planes.get(), 0, |
| 1518 sizeof(struct v4l2_plane) * output_planes_count_); | 1515 sizeof(struct v4l2_plane) * output_planes_count_); |
| 1519 qbuf.index = buffer; | 1516 qbuf.index = buffer; |
| 1520 qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1517 qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1521 qbuf.memory = V4L2_MEMORY_MMAP; | 1518 qbuf.memory = V4L2_MEMORY_MMAP; |
| 1522 qbuf.m.planes = qbuf_planes.get(); | 1519 qbuf.m.planes = qbuf_planes.get(); |
| 1523 qbuf.length = output_planes_count_; | 1520 qbuf.length = output_planes_count_; |
| 1524 DVLOGF(2) << "qbuf.index=" << qbuf.index; | 1521 DVLOGF(3) << "qbuf.index=" << qbuf.index; |
|
Pawel Osciak
2017/05/23 09:49:21
Perhaps 4?
Owen Lin
2017/06/02 08:51:43
Done.
| |
| 1525 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf); | 1522 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf); |
| 1526 free_output_buffers_.pop_front(); | 1523 free_output_buffers_.pop_front(); |
| 1527 output_record.state = kAtDevice; | 1524 output_record.state = kAtDevice; |
| 1528 output_buffer_queued_count_++; | 1525 output_buffer_queued_count_++; |
| 1529 return true; | 1526 return true; |
| 1530 } | 1527 } |
| 1531 | 1528 |
| 1532 void V4L2VideoDecodeAccelerator::ReusePictureBufferTask( | 1529 void V4L2VideoDecodeAccelerator::ReusePictureBufferTask( |
| 1533 int32_t picture_buffer_id, | 1530 int32_t picture_buffer_id, |
| 1534 std::unique_ptr<EGLSyncKHRRef> egl_sync_ref) { | 1531 std::unique_ptr<EGLSyncKHRRef> egl_sync_ref) { |
| 1535 DVLOGF(3) << "picture_buffer_id=" << picture_buffer_id; | 1532 DVLOGF(4) << "picture_buffer_id=" << picture_buffer_id; |
| 1536 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1533 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 1537 TRACE_EVENT0("Video Decoder", "V4L2VDA::ReusePictureBufferTask"); | 1534 TRACE_EVENT0("Video Decoder", "V4L2VDA::ReusePictureBufferTask"); |
| 1538 | 1535 |
| 1539 // We run ReusePictureBufferTask even if we're in kResetting. | 1536 // We run ReusePictureBufferTask even if we're in kResetting. |
| 1540 if (decoder_state_ == kError) { | 1537 if (decoder_state_ == kError) { |
| 1541 DVLOGF(2) << "early out: kError state"; | 1538 DVLOGF(4) << "early out: kError state"; |
| 1542 return; | 1539 return; |
| 1543 } | 1540 } |
| 1544 | 1541 |
| 1545 if (decoder_state_ == kChangingResolution) { | 1542 if (decoder_state_ == kChangingResolution) { |
| 1546 DVLOGF(2) << "early out: kChangingResolution"; | 1543 DVLOGF(4) << "early out: kChangingResolution"; |
| 1547 return; | 1544 return; |
| 1548 } | 1545 } |
| 1549 | 1546 |
| 1550 size_t index; | 1547 size_t index; |
| 1551 for (index = 0; index < output_buffer_map_.size(); ++index) | 1548 for (index = 0; index < output_buffer_map_.size(); ++index) |
| 1552 if (output_buffer_map_[index].picture_id == picture_buffer_id) | 1549 if (output_buffer_map_[index].picture_id == picture_buffer_id) |
| 1553 break; | 1550 break; |
| 1554 | 1551 |
| 1555 if (index >= output_buffer_map_.size()) { | 1552 if (index >= output_buffer_map_.size()) { |
| 1556 // It's possible that we've already posted a DismissPictureBuffer for this | 1553 // It's possible that we've already posted a DismissPictureBuffer for this |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1577 if (egl_sync_ref) { | 1574 if (egl_sync_ref) { |
| 1578 output_record.egl_sync = egl_sync_ref->egl_sync; | 1575 output_record.egl_sync = egl_sync_ref->egl_sync; |
| 1579 // Take ownership of the EGLSync. | 1576 // Take ownership of the EGLSync. |
| 1580 egl_sync_ref->egl_sync = EGL_NO_SYNC_KHR; | 1577 egl_sync_ref->egl_sync = EGL_NO_SYNC_KHR; |
| 1581 } | 1578 } |
| 1582 // We got a buffer back, so enqueue it back. | 1579 // We got a buffer back, so enqueue it back. |
| 1583 Enqueue(); | 1580 Enqueue(); |
| 1584 } | 1581 } |
| 1585 | 1582 |
| 1586 void V4L2VideoDecodeAccelerator::FlushTask() { | 1583 void V4L2VideoDecodeAccelerator::FlushTask() { |
| 1587 DVLOGF(3); | 1584 DVLOGF(2); |
| 1588 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1585 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 1589 TRACE_EVENT0("Video Decoder", "V4L2VDA::FlushTask"); | 1586 TRACE_EVENT0("Video Decoder", "V4L2VDA::FlushTask"); |
| 1590 | 1587 |
| 1591 // Flush outstanding buffers. | 1588 // Flush outstanding buffers. |
| 1592 if (decoder_state_ == kInitialized) { | 1589 if (decoder_state_ == kInitialized) { |
| 1593 // There's nothing in the pipe, so return done immediately. | 1590 // There's nothing in the pipe, so return done immediately. |
| 1594 DVLOGF(3) << "returning flush"; | 1591 DVLOGF(2) << "returning flush"; |
| 1595 child_task_runner_->PostTask(FROM_HERE, | 1592 child_task_runner_->PostTask(FROM_HERE, |
| 1596 base::Bind(&Client::NotifyFlushDone, client_)); | 1593 base::Bind(&Client::NotifyFlushDone, client_)); |
| 1597 return; | 1594 return; |
| 1598 } else if (decoder_state_ == kError) { | 1595 } else if (decoder_state_ == kError) { |
| 1599 DVLOGF(2) << "early out: kError state"; | 1596 DVLOGF(2) << "early out: kError state"; |
| 1600 return; | 1597 return; |
| 1601 } | 1598 } |
| 1602 | 1599 |
| 1603 // We don't support stacked flushing. | 1600 // We don't support stacked flushing. |
| 1604 DCHECK(!decoder_flushing_); | 1601 DCHECK(!decoder_flushing_); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1658 // For now, do the streamoff-streamon cycle to satisfy Exynos and not freeze | 1655 // For now, do the streamoff-streamon cycle to satisfy Exynos and not freeze |
| 1659 // when doing MSE. This should be harmless otherwise. | 1656 // when doing MSE. This should be harmless otherwise. |
| 1660 if (!(StopDevicePoll() && StopOutputStream() && StopInputStream())) | 1657 if (!(StopDevicePoll() && StopOutputStream() && StopInputStream())) |
| 1661 return; | 1658 return; |
| 1662 | 1659 |
| 1663 if (!StartDevicePoll()) | 1660 if (!StartDevicePoll()) |
| 1664 return; | 1661 return; |
| 1665 | 1662 |
| 1666 decoder_delay_bitstream_buffer_id_ = -1; | 1663 decoder_delay_bitstream_buffer_id_ = -1; |
| 1667 decoder_flushing_ = false; | 1664 decoder_flushing_ = false; |
| 1668 DVLOGF(3) << "returning flush"; | 1665 DVLOGF(2) << "returning flush"; |
| 1669 child_task_runner_->PostTask(FROM_HERE, | 1666 child_task_runner_->PostTask(FROM_HERE, |
| 1670 base::Bind(&Client::NotifyFlushDone, client_)); | 1667 base::Bind(&Client::NotifyFlushDone, client_)); |
| 1671 | 1668 |
| 1672 // While we were flushing, we early-outed DecodeBufferTask()s. | 1669 // While we were flushing, we early-outed DecodeBufferTask()s. |
| 1673 ScheduleDecodeBufferTaskIfNeeded(); | 1670 ScheduleDecodeBufferTaskIfNeeded(); |
| 1674 } | 1671 } |
| 1675 | 1672 |
| 1676 bool V4L2VideoDecodeAccelerator::IsDecoderCmdSupported() { | 1673 bool V4L2VideoDecodeAccelerator::IsDecoderCmdSupported() { |
| 1677 // CMD_STOP should always succeed. If the decoder is started, the command can | 1674 // CMD_STOP should always succeed. If the decoder is started, the command can |
| 1678 // flush it. If the decoder is stopped, the command does nothing. We use this | 1675 // flush it. If the decoder is stopped, the command does nothing. We use this |
| 1679 // to know if a driver supports V4L2_DEC_CMD_STOP to flush. | 1676 // to know if a driver supports V4L2_DEC_CMD_STOP to flush. |
| 1680 struct v4l2_decoder_cmd cmd; | 1677 struct v4l2_decoder_cmd cmd; |
| 1681 memset(&cmd, 0, sizeof(cmd)); | 1678 memset(&cmd, 0, sizeof(cmd)); |
| 1682 cmd.cmd = V4L2_DEC_CMD_STOP; | 1679 cmd.cmd = V4L2_DEC_CMD_STOP; |
| 1683 if (device_->Ioctl(VIDIOC_TRY_DECODER_CMD, &cmd) != 0) { | 1680 if (device_->Ioctl(VIDIOC_TRY_DECODER_CMD, &cmd) != 0) { |
| 1684 DVLOGF(3) "V4L2_DEC_CMD_STOP is not supported."; | 1681 DVLOGF(2) "V4L2_DEC_CMD_STOP is not supported."; |
| 1685 return false; | 1682 return false; |
| 1686 } | 1683 } |
| 1687 | 1684 |
| 1688 return true; | 1685 return true; |
| 1689 } | 1686 } |
| 1690 | 1687 |
| 1691 bool V4L2VideoDecodeAccelerator::SendDecoderCmdStop() { | 1688 bool V4L2VideoDecodeAccelerator::SendDecoderCmdStop() { |
| 1692 DVLOGF(2); | 1689 DVLOGF(2); |
| 1693 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1690 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 1694 DCHECK(!flush_awaiting_last_output_buffer_); | 1691 DCHECK(!flush_awaiting_last_output_buffer_); |
| 1695 | 1692 |
| 1696 struct v4l2_decoder_cmd cmd; | 1693 struct v4l2_decoder_cmd cmd; |
| 1697 memset(&cmd, 0, sizeof(cmd)); | 1694 memset(&cmd, 0, sizeof(cmd)); |
| 1698 cmd.cmd = V4L2_DEC_CMD_STOP; | 1695 cmd.cmd = V4L2_DEC_CMD_STOP; |
| 1699 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_DECODER_CMD, &cmd); | 1696 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_DECODER_CMD, &cmd); |
| 1700 flush_awaiting_last_output_buffer_ = true; | 1697 flush_awaiting_last_output_buffer_ = true; |
| 1701 | 1698 |
| 1702 return true; | 1699 return true; |
| 1703 } | 1700 } |
| 1704 | 1701 |
| 1705 void V4L2VideoDecodeAccelerator::ResetTask() { | 1702 void V4L2VideoDecodeAccelerator::ResetTask() { |
| 1706 DVLOGF(3); | 1703 DVLOGF(2); |
| 1707 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1704 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 1708 TRACE_EVENT0("Video Decoder", "V4L2VDA::ResetTask"); | 1705 TRACE_EVENT0("Video Decoder", "V4L2VDA::ResetTask"); |
| 1709 | 1706 |
| 1710 if (decoder_state_ == kError) { | 1707 if (decoder_state_ == kError) { |
| 1711 DVLOGF(2) << "early out: kError state"; | 1708 DVLOGF(2) << "early out: kError state"; |
| 1712 return; | 1709 return; |
| 1713 } | 1710 } |
| 1714 decoder_current_bitstream_buffer_.reset(); | 1711 decoder_current_bitstream_buffer_.reset(); |
| 1715 while (!decoder_input_queue_.empty()) | 1712 while (!decoder_input_queue_.empty()) |
| 1716 decoder_input_queue_.pop(); | 1713 decoder_input_queue_.pop(); |
| 1717 | 1714 |
| 1718 decoder_current_input_buffer_ = -1; | 1715 decoder_current_input_buffer_ = -1; |
| 1719 | 1716 |
| 1720 // If we are in the middle of switching resolutions or awaiting picture | 1717 // If we are in the middle of switching resolutions or awaiting picture |
| 1721 // buffers, postpone reset until it's done. We don't have to worry about | 1718 // buffers, postpone reset until it's done. We don't have to worry about |
| 1722 // timing of this wrt to decoding, because output pipe is already | 1719 // timing of this wrt to decoding, because output pipe is already |
| 1723 // stopped if we are changing resolution. We will come back here after | 1720 // stopped if we are changing resolution. We will come back here after |
| 1724 // we are done. | 1721 // we are done. |
| 1725 DCHECK(!reset_pending_); | 1722 DCHECK(!reset_pending_); |
| 1726 if (decoder_state_ == kChangingResolution || | 1723 if (decoder_state_ == kChangingResolution || |
| 1727 decoder_state_ == kAwaitingPictureBuffers) { | 1724 decoder_state_ == kAwaitingPictureBuffers) { |
| 1728 reset_pending_ = true; | 1725 reset_pending_ = true; |
| 1729 return; | 1726 return; |
| 1730 } | 1727 } |
| 1731 FinishReset(); | 1728 FinishReset(); |
| 1732 } | 1729 } |
| 1733 | 1730 |
| 1734 void V4L2VideoDecodeAccelerator::FinishReset() { | 1731 void V4L2VideoDecodeAccelerator::FinishReset() { |
| 1735 DVLOGF(3); | 1732 DVLOGF(2); |
| 1736 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1733 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 1737 | 1734 |
| 1738 reset_pending_ = false; | 1735 reset_pending_ = false; |
| 1739 // After the output stream is stopped, the codec should not post any | 1736 // After the output stream is stopped, the codec should not post any |
| 1740 // resolution change events. So we dequeue the resolution change event | 1737 // resolution change events. So we dequeue the resolution change event |
| 1741 // afterwards. The event could be posted before or while stopping the output | 1738 // afterwards. The event could be posted before or while stopping the output |
| 1742 // stream. The codec will expect the buffer of new size after the seek, so | 1739 // stream. The codec will expect the buffer of new size after the seek, so |
| 1743 // we need to handle the resolution change event first. | 1740 // we need to handle the resolution change event first. |
| 1744 if (!(StopDevicePoll() && StopOutputStream())) | 1741 if (!(StopDevicePoll() && StopOutputStream())) |
| 1745 return; | 1742 return; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1767 // Mark that we're resetting, then enqueue a ResetDoneTask(). All intervening | 1764 // Mark that we're resetting, then enqueue a ResetDoneTask(). All intervening |
| 1768 // jobs will early-out in the kResetting state. | 1765 // jobs will early-out in the kResetting state. |
| 1769 decoder_state_ = kResetting; | 1766 decoder_state_ = kResetting; |
| 1770 SendPictureReady(); // Send all pending PictureReady. | 1767 SendPictureReady(); // Send all pending PictureReady. |
| 1771 decoder_thread_.task_runner()->PostTask( | 1768 decoder_thread_.task_runner()->PostTask( |
| 1772 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::ResetDoneTask, | 1769 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::ResetDoneTask, |
| 1773 base::Unretained(this))); | 1770 base::Unretained(this))); |
| 1774 } | 1771 } |
| 1775 | 1772 |
| 1776 void V4L2VideoDecodeAccelerator::ResetDoneTask() { | 1773 void V4L2VideoDecodeAccelerator::ResetDoneTask() { |
| 1777 DVLOGF(3); | 1774 DVLOGF(2); |
| 1778 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1775 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 1779 TRACE_EVENT0("Video Decoder", "V4L2VDA::ResetDoneTask"); | 1776 TRACE_EVENT0("Video Decoder", "V4L2VDA::ResetDoneTask"); |
| 1780 | 1777 |
| 1781 if (decoder_state_ == kError) { | 1778 if (decoder_state_ == kError) { |
| 1782 DVLOGF(2) << "early out: kError state"; | 1779 DVLOGF(2) << "early out: kError state"; |
| 1783 return; | 1780 return; |
| 1784 } | 1781 } |
| 1785 | 1782 |
| 1786 // Start poll thread if NotifyFlushDoneIfNeeded has not already. | 1783 // Start poll thread if NotifyFlushDoneIfNeeded has not already. |
| 1787 if (!device_poll_thread_.IsRunning()) { | 1784 if (!device_poll_thread_.IsRunning()) { |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1801 decoder_partial_frame_pending_ = false; | 1798 decoder_partial_frame_pending_ = false; |
| 1802 decoder_delay_bitstream_buffer_id_ = -1; | 1799 decoder_delay_bitstream_buffer_id_ = -1; |
| 1803 child_task_runner_->PostTask(FROM_HERE, | 1800 child_task_runner_->PostTask(FROM_HERE, |
| 1804 base::Bind(&Client::NotifyResetDone, client_)); | 1801 base::Bind(&Client::NotifyResetDone, client_)); |
| 1805 | 1802 |
| 1806 // While we were resetting, we early-outed DecodeBufferTask()s. | 1803 // While we were resetting, we early-outed DecodeBufferTask()s. |
| 1807 ScheduleDecodeBufferTaskIfNeeded(); | 1804 ScheduleDecodeBufferTaskIfNeeded(); |
| 1808 } | 1805 } |
| 1809 | 1806 |
| 1810 void V4L2VideoDecodeAccelerator::DestroyTask() { | 1807 void V4L2VideoDecodeAccelerator::DestroyTask() { |
| 1811 DVLOGF(3); | 1808 DVLOGF(2); |
| 1812 TRACE_EVENT0("Video Decoder", "V4L2VDA::DestroyTask"); | 1809 TRACE_EVENT0("Video Decoder", "V4L2VDA::DestroyTask"); |
| 1813 | 1810 |
| 1814 // DestroyTask() should run regardless of decoder_state_. | 1811 // DestroyTask() should run regardless of decoder_state_. |
| 1815 | 1812 |
| 1816 StopDevicePoll(); | 1813 StopDevicePoll(); |
| 1817 StopOutputStream(); | 1814 StopOutputStream(); |
| 1818 StopInputStream(); | 1815 StopInputStream(); |
| 1819 | 1816 |
| 1820 decoder_current_bitstream_buffer_.reset(); | 1817 decoder_current_bitstream_buffer_.reset(); |
| 1821 decoder_current_input_buffer_ = -1; | 1818 decoder_current_input_buffer_ = -1; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1872 // Clear the interrupt now, to be sure. | 1869 // Clear the interrupt now, to be sure. |
| 1873 if (!device_->ClearDevicePollInterrupt()) { | 1870 if (!device_->ClearDevicePollInterrupt()) { |
| 1874 NOTIFY_ERROR(PLATFORM_FAILURE); | 1871 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1875 return false; | 1872 return false; |
| 1876 } | 1873 } |
| 1877 DVLOGF(3) << "device poll stopped"; | 1874 DVLOGF(3) << "device poll stopped"; |
| 1878 return true; | 1875 return true; |
| 1879 } | 1876 } |
| 1880 | 1877 |
| 1881 bool V4L2VideoDecodeAccelerator::StopOutputStream() { | 1878 bool V4L2VideoDecodeAccelerator::StopOutputStream() { |
| 1882 DVLOGF(3); | 1879 DVLOGF(2); |
| 1883 if (!output_streamon_) | 1880 if (!output_streamon_) |
| 1884 return true; | 1881 return true; |
| 1885 | 1882 |
| 1886 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1883 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1887 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMOFF, &type); | 1884 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMOFF, &type); |
| 1888 output_streamon_ = false; | 1885 output_streamon_ = false; |
| 1889 | 1886 |
| 1890 // Output stream is stopped. No need to wait for the buffer anymore. | 1887 // Output stream is stopped. No need to wait for the buffer anymore. |
| 1891 flush_awaiting_last_output_buffer_ = false; | 1888 flush_awaiting_last_output_buffer_ = false; |
| 1892 | 1889 |
| 1893 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { | 1890 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { |
| 1894 // After streamoff, the device drops ownership of all buffers, even if we | 1891 // After streamoff, the device drops ownership of all buffers, even if we |
| 1895 // don't dequeue them explicitly. Some of them may still be owned by the | 1892 // don't dequeue them explicitly. Some of them may still be owned by the |
| 1896 // client however. Reuse only those that aren't. | 1893 // client however. Reuse only those that aren't. |
| 1897 OutputRecord& output_record = output_buffer_map_[i]; | 1894 OutputRecord& output_record = output_buffer_map_[i]; |
| 1898 if (output_record.state == kAtDevice) { | 1895 if (output_record.state == kAtDevice) { |
| 1899 output_record.state = kFree; | 1896 output_record.state = kFree; |
| 1900 free_output_buffers_.push_back(i); | 1897 free_output_buffers_.push_back(i); |
| 1901 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); | 1898 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); |
| 1902 } | 1899 } |
| 1903 } | 1900 } |
| 1904 output_buffer_queued_count_ = 0; | 1901 output_buffer_queued_count_ = 0; |
| 1905 return true; | 1902 return true; |
| 1906 } | 1903 } |
| 1907 | 1904 |
| 1908 bool V4L2VideoDecodeAccelerator::StopInputStream() { | 1905 bool V4L2VideoDecodeAccelerator::StopInputStream() { |
| 1909 DVLOGF(3); | 1906 DVLOGF(2); |
| 1910 if (!input_streamon_) | 1907 if (!input_streamon_) |
| 1911 return true; | 1908 return true; |
| 1912 | 1909 |
| 1913 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1910 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 1914 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMOFF, &type); | 1911 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMOFF, &type); |
| 1915 input_streamon_ = false; | 1912 input_streamon_ = false; |
| 1916 | 1913 |
| 1917 // Reset accounting info for input. | 1914 // Reset accounting info for input. |
| 1918 while (!input_ready_queue_.empty()) | 1915 while (!input_ready_queue_.empty()) |
| 1919 input_ready_queue_.pop(); | 1916 input_ready_queue_.pop(); |
| 1920 free_input_buffers_.clear(); | 1917 free_input_buffers_.clear(); |
| 1921 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { | 1918 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { |
| 1922 free_input_buffers_.push_back(i); | 1919 free_input_buffers_.push_back(i); |
| 1923 input_buffer_map_[i].at_device = false; | 1920 input_buffer_map_[i].at_device = false; |
| 1924 input_buffer_map_[i].bytes_used = 0; | 1921 input_buffer_map_[i].bytes_used = 0; |
| 1925 input_buffer_map_[i].input_id = -1; | 1922 input_buffer_map_[i].input_id = -1; |
| 1926 } | 1923 } |
| 1927 input_buffer_queued_count_ = 0; | 1924 input_buffer_queued_count_ = 0; |
| 1928 | 1925 |
| 1929 return true; | 1926 return true; |
| 1930 } | 1927 } |
| 1931 | 1928 |
| 1932 void V4L2VideoDecodeAccelerator::StartResolutionChange() { | 1929 void V4L2VideoDecodeAccelerator::StartResolutionChange() { |
| 1933 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1930 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 1934 DCHECK_NE(decoder_state_, kUninitialized); | 1931 DCHECK_NE(decoder_state_, kUninitialized); |
| 1935 DCHECK_NE(decoder_state_, kResetting); | 1932 DCHECK_NE(decoder_state_, kResetting); |
| 1936 | 1933 |
| 1937 DVLOGF(3) << "Initiate resolution change"; | 1934 DVLOGF(2) << "Initiate resolution change"; |
| 1938 | 1935 |
| 1939 if (!(StopDevicePoll() && StopOutputStream())) | 1936 if (!(StopDevicePoll() && StopOutputStream())) |
| 1940 return; | 1937 return; |
| 1941 | 1938 |
| 1942 decoder_state_ = kChangingResolution; | 1939 decoder_state_ = kChangingResolution; |
| 1943 SendPictureReady(); // Send all pending PictureReady. | 1940 SendPictureReady(); // Send all pending PictureReady. |
| 1944 | 1941 |
| 1945 if (!image_processor_bitstream_buffer_ids_.empty()) { | 1942 if (!image_processor_bitstream_buffer_ids_.empty()) { |
| 1946 DVLOGF(3) << "Wait image processor to finish before destroying buffers."; | 1943 DVLOGF(2) << "Wait image processor to finish before destroying buffers."; |
| 1947 return; | 1944 return; |
| 1948 } | 1945 } |
| 1949 | 1946 |
| 1950 if (image_processor_) | 1947 if (image_processor_) |
| 1951 image_processor_.release()->Destroy(); | 1948 image_processor_.release()->Destroy(); |
| 1952 | 1949 |
| 1953 if (!DestroyOutputBuffers()) { | 1950 if (!DestroyOutputBuffers()) { |
| 1954 LOGF(ERROR) << "Failed destroying output buffers."; | 1951 LOGF(ERROR) << "Failed destroying output buffers."; |
| 1955 NOTIFY_ERROR(PLATFORM_FAILURE); | 1952 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1956 return; | 1953 return; |
| 1957 } | 1954 } |
| 1958 | 1955 |
| 1959 FinishResolutionChange(); | 1956 FinishResolutionChange(); |
| 1960 } | 1957 } |
| 1961 | 1958 |
| 1962 void V4L2VideoDecodeAccelerator::FinishResolutionChange() { | 1959 void V4L2VideoDecodeAccelerator::FinishResolutionChange() { |
| 1963 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1960 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 1964 DCHECK_EQ(decoder_state_, kChangingResolution); | 1961 DCHECK_EQ(decoder_state_, kChangingResolution); |
| 1965 DVLOGF(3); | 1962 DVLOGF(2); |
| 1966 | 1963 |
| 1967 if (decoder_state_ == kError) { | 1964 if (decoder_state_ == kError) { |
| 1968 DVLOGF(2) << "early out: kError state"; | 1965 DVLOGF(2) << "early out: kError state"; |
| 1969 return; | 1966 return; |
| 1970 } | 1967 } |
| 1971 | 1968 |
| 1972 struct v4l2_format format; | 1969 struct v4l2_format format; |
| 1973 bool again; | 1970 bool again; |
| 1974 gfx::Size visible_size; | 1971 gfx::Size visible_size; |
| 1975 bool ret = GetFormatInfo(&format, &visible_size, &again); | 1972 bool ret = GetFormatInfo(&format, &visible_size, &again); |
| 1976 if (!ret || again) { | 1973 if (!ret || again) { |
| 1977 LOGF(ERROR) << "Couldn't get format information after resolution change"; | 1974 LOGF(ERROR) << "Couldn't get format information after resolution change"; |
| 1978 NOTIFY_ERROR(PLATFORM_FAILURE); | 1975 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1979 return; | 1976 return; |
| 1980 } | 1977 } |
| 1981 | 1978 |
| 1982 if (!CreateBuffersForFormat(format, visible_size)) { | 1979 if (!CreateBuffersForFormat(format, visible_size)) { |
| 1983 LOGF(ERROR) << "Couldn't reallocate buffers after resolution change"; | 1980 LOGF(ERROR) << "Couldn't reallocate buffers after resolution change"; |
| 1984 NOTIFY_ERROR(PLATFORM_FAILURE); | 1981 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1985 return; | 1982 return; |
| 1986 } | 1983 } |
| 1987 | 1984 |
| 1988 if (!StartDevicePoll()) | 1985 if (!StartDevicePoll()) |
| 1989 return; | 1986 return; |
| 1990 } | 1987 } |
| 1991 | 1988 |
| 1992 void V4L2VideoDecodeAccelerator::DevicePollTask(bool poll_device) { | 1989 void V4L2VideoDecodeAccelerator::DevicePollTask(bool poll_device) { |
| 1993 DVLOGF(3); | 1990 DVLOGF(3); |
|
Pawel Osciak
2017/05/23 09:49:21
4 perhaps?
Owen Lin
2017/06/02 08:51:43
Done.
| |
| 1994 DCHECK(device_poll_thread_.task_runner()->BelongsToCurrentThread()); | 1991 DCHECK(device_poll_thread_.task_runner()->BelongsToCurrentThread()); |
| 1995 TRACE_EVENT0("Video Decoder", "V4L2VDA::DevicePollTask"); | 1992 TRACE_EVENT0("Video Decoder", "V4L2VDA::DevicePollTask"); |
| 1996 | 1993 |
| 1997 bool event_pending = false; | 1994 bool event_pending = false; |
| 1998 | 1995 |
| 1999 if (!device_->Poll(poll_device, &event_pending)) { | 1996 if (!device_->Poll(poll_device, &event_pending)) { |
| 2000 NOTIFY_ERROR(PLATFORM_FAILURE); | 1997 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 2001 return; | 1998 return; |
| 2002 } | 1999 } |
| 2003 | 2000 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2089 if (!V4L2ImageProcessor::TryOutputFormat( | 2086 if (!V4L2ImageProcessor::TryOutputFormat( |
| 2090 output_format_fourcc_, egl_image_format_fourcc_, &egl_image_size_, | 2087 output_format_fourcc_, egl_image_format_fourcc_, &egl_image_size_, |
| 2091 &egl_image_planes_count_)) { | 2088 &egl_image_planes_count_)) { |
| 2092 LOGF(ERROR) << "Fail to get output size and plane count of processor"; | 2089 LOGF(ERROR) << "Fail to get output size and plane count of processor"; |
| 2093 return false; | 2090 return false; |
| 2094 } | 2091 } |
| 2095 } else { | 2092 } else { |
| 2096 egl_image_size_ = coded_size_; | 2093 egl_image_size_ = coded_size_; |
| 2097 egl_image_planes_count_ = output_planes_count_; | 2094 egl_image_planes_count_ = output_planes_count_; |
| 2098 } | 2095 } |
| 2099 DVLOGF(3) << "new resolution: " << coded_size_.ToString() | 2096 DVLOGF(2) << "new resolution: " << coded_size_.ToString() |
| 2100 << ", visible size: " << visible_size_.ToString() | 2097 << ", visible size: " << visible_size_.ToString() |
| 2101 << ", decoder output planes count: " << output_planes_count_ | 2098 << ", decoder output planes count: " << output_planes_count_ |
| 2102 << ", EGLImage size: " << egl_image_size_.ToString() | 2099 << ", EGLImage size: " << egl_image_size_.ToString() |
| 2103 << ", EGLImage plane count: " << egl_image_planes_count_; | 2100 << ", EGLImage plane count: " << egl_image_planes_count_; |
| 2104 | 2101 |
| 2105 return CreateOutputBuffers(); | 2102 return CreateOutputBuffers(); |
| 2106 } | 2103 } |
| 2107 | 2104 |
| 2108 gfx::Size V4L2VideoDecodeAccelerator::GetVisibleSize( | 2105 gfx::Size V4L2VideoDecodeAccelerator::GetVisibleSize( |
| 2109 const gfx::Size& coded_size) { | 2106 const gfx::Size& coded_size) { |
| 2110 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 2107 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 2111 | 2108 |
| 2112 struct v4l2_crop crop_arg; | 2109 struct v4l2_crop crop_arg; |
| 2113 memset(&crop_arg, 0, sizeof(crop_arg)); | 2110 memset(&crop_arg, 0, sizeof(crop_arg)); |
| 2114 crop_arg.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 2111 crop_arg.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 2115 | 2112 |
| 2116 if (device_->Ioctl(VIDIOC_G_CROP, &crop_arg) != 0) { | 2113 if (device_->Ioctl(VIDIOC_G_CROP, &crop_arg) != 0) { |
| 2117 PLOGF(ERROR) << "ioctl() VIDIOC_G_CROP failed"; | 2114 PLOGF(ERROR) << "ioctl() VIDIOC_G_CROP failed"; |
| 2118 return coded_size; | 2115 return coded_size; |
| 2119 } | 2116 } |
| 2120 | 2117 |
| 2121 gfx::Rect rect(crop_arg.c.left, crop_arg.c.top, crop_arg.c.width, | 2118 gfx::Rect rect(crop_arg.c.left, crop_arg.c.top, crop_arg.c.width, |
| 2122 crop_arg.c.height); | 2119 crop_arg.c.height); |
| 2123 DVLOGF(3) << "visible rectangle is " << rect.ToString(); | 2120 DVLOGF(2) << "visible rectangle is " << rect.ToString(); |
| 2124 if (!gfx::Rect(coded_size).Contains(rect)) { | 2121 if (!gfx::Rect(coded_size).Contains(rect)) { |
| 2125 DLOGF(ERROR) << "visible rectangle " << rect.ToString() | 2122 DLOGF(ERROR) << "visible rectangle " << rect.ToString() |
| 2126 << " is not inside coded size " << coded_size.ToString(); | 2123 << " is not inside coded size " << coded_size.ToString(); |
| 2127 return coded_size; | 2124 return coded_size; |
| 2128 } | 2125 } |
| 2129 if (rect.IsEmpty()) { | 2126 if (rect.IsEmpty()) { |
| 2130 DLOGF(ERROR) << "visible size is empty"; | 2127 DLOGF(ERROR) << "visible size is empty"; |
| 2131 return coded_size; | 2128 return coded_size; |
| 2132 } | 2129 } |
| 2133 | 2130 |
| 2134 // Chrome assume picture frame is coded at (0, 0). | 2131 // Chrome assume picture frame is coded at (0, 0). |
| 2135 if (!rect.origin().IsOrigin()) { | 2132 if (!rect.origin().IsOrigin()) { |
| 2136 DLOGF(ERROR) << "Unexpected visible rectangle " << rect.ToString() | 2133 DLOGF(ERROR) << "Unexpected visible rectangle " << rect.ToString() |
| 2137 << ", top-left is not origin"; | 2134 << ", top-left is not origin"; |
| 2138 return coded_size; | 2135 return coded_size; |
| 2139 } | 2136 } |
| 2140 | 2137 |
| 2141 return rect.size(); | 2138 return rect.size(); |
| 2142 } | 2139 } |
| 2143 | 2140 |
| 2144 bool V4L2VideoDecodeAccelerator::CreateInputBuffers() { | 2141 bool V4L2VideoDecodeAccelerator::CreateInputBuffers() { |
| 2145 DVLOGF(3); | 2142 DVLOGF(2); |
| 2146 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 2143 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 2147 // We always run this as we prepare to initialize. | 2144 // We always run this as we prepare to initialize. |
| 2148 DCHECK_EQ(decoder_state_, kInitialized); | 2145 DCHECK_EQ(decoder_state_, kInitialized); |
| 2149 DCHECK(!input_streamon_); | 2146 DCHECK(!input_streamon_); |
| 2150 DCHECK(input_buffer_map_.empty()); | 2147 DCHECK(input_buffer_map_.empty()); |
| 2151 | 2148 |
| 2152 struct v4l2_requestbuffers reqbufs; | 2149 struct v4l2_requestbuffers reqbufs; |
| 2153 memset(&reqbufs, 0, sizeof(reqbufs)); | 2150 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 2154 reqbufs.count = kInputBufferCount; | 2151 reqbufs.count = kInputBufferCount; |
| 2155 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 2152 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2289 std::vector<uint32_t> processor_input_formats = | 2286 std::vector<uint32_t> processor_input_formats = |
| 2290 V4L2ImageProcessor::GetSupportedInputFormats(); | 2287 V4L2ImageProcessor::GetSupportedInputFormats(); |
| 2291 | 2288 |
| 2292 struct v4l2_fmtdesc fmtdesc; | 2289 struct v4l2_fmtdesc fmtdesc; |
| 2293 memset(&fmtdesc, 0, sizeof(fmtdesc)); | 2290 memset(&fmtdesc, 0, sizeof(fmtdesc)); |
| 2294 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 2291 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 2295 while (device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0) { | 2292 while (device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0) { |
| 2296 if (std::find(processor_input_formats.begin(), | 2293 if (std::find(processor_input_formats.begin(), |
| 2297 processor_input_formats.end(), | 2294 processor_input_formats.end(), |
| 2298 fmtdesc.pixelformat) != processor_input_formats.end()) { | 2295 fmtdesc.pixelformat) != processor_input_formats.end()) { |
| 2299 DVLOGF(1) << "Image processor input format=" << fmtdesc.description; | 2296 DVLOGF(2) << "Image processor input format=" << fmtdesc.description; |
| 2300 return fmtdesc.pixelformat; | 2297 return fmtdesc.pixelformat; |
| 2301 } | 2298 } |
| 2302 ++fmtdesc.index; | 2299 ++fmtdesc.index; |
| 2303 } | 2300 } |
| 2304 return 0; | 2301 return 0; |
| 2305 } | 2302 } |
| 2306 | 2303 |
| 2307 uint32_t V4L2VideoDecodeAccelerator::FindImageProcessorOutputFormat() { | 2304 uint32_t V4L2VideoDecodeAccelerator::FindImageProcessorOutputFormat() { |
| 2308 // Prefer YVU420 and NV12 because ArcGpuVideoDecodeAccelerator only supports | 2305 // Prefer YVU420 and NV12 because ArcGpuVideoDecodeAccelerator only supports |
| 2309 // single physical plane. Prefer YVU420 over NV12 because chrome rendering | 2306 // single physical plane. Prefer YVU420 over NV12 because chrome rendering |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 2320 | 2317 |
| 2321 std::vector<uint32_t> processor_output_formats = | 2318 std::vector<uint32_t> processor_output_formats = |
| 2322 V4L2ImageProcessor::GetSupportedOutputFormats(); | 2319 V4L2ImageProcessor::GetSupportedOutputFormats(); |
| 2323 | 2320 |
| 2324 // Move the preferred formats to the front. | 2321 // Move the preferred formats to the front. |
| 2325 std::sort(processor_output_formats.begin(), processor_output_formats.end(), | 2322 std::sort(processor_output_formats.begin(), processor_output_formats.end(), |
| 2326 preferred_formats_first); | 2323 preferred_formats_first); |
| 2327 | 2324 |
| 2328 for (uint32_t processor_output_format : processor_output_formats) { | 2325 for (uint32_t processor_output_format : processor_output_formats) { |
| 2329 if (device_->CanCreateEGLImageFrom(processor_output_format)) { | 2326 if (device_->CanCreateEGLImageFrom(processor_output_format)) { |
| 2330 DVLOGF(1) << "Image processor output format=" << processor_output_format; | 2327 DVLOGF(2) << "Image processor output format=" << processor_output_format; |
| 2331 return processor_output_format; | 2328 return processor_output_format; |
| 2332 } | 2329 } |
| 2333 } | 2330 } |
| 2334 | 2331 |
| 2335 return 0; | 2332 return 0; |
| 2336 } | 2333 } |
| 2337 | 2334 |
| 2338 bool V4L2VideoDecodeAccelerator::ResetImageProcessor() { | 2335 bool V4L2VideoDecodeAccelerator::ResetImageProcessor() { |
| 2339 DVLOGF(3); | 2336 DVLOGF(2); |
| 2340 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 2337 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 2341 | 2338 |
| 2342 if (!image_processor_->Reset()) | 2339 if (!image_processor_->Reset()) |
| 2343 return false; | 2340 return false; |
| 2344 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { | 2341 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { |
| 2345 OutputRecord& output_record = output_buffer_map_[i]; | 2342 OutputRecord& output_record = output_buffer_map_[i]; |
| 2346 if (output_record.state == kAtProcessor) { | 2343 if (output_record.state == kAtProcessor) { |
| 2347 output_record.state = kFree; | 2344 output_record.state = kFree; |
| 2348 free_output_buffers_.push_back(i); | 2345 free_output_buffers_.push_back(i); |
| 2349 } | 2346 } |
| 2350 } | 2347 } |
| 2351 while (!image_processor_bitstream_buffer_ids_.empty()) | 2348 while (!image_processor_bitstream_buffer_ids_.empty()) |
| 2352 image_processor_bitstream_buffer_ids_.pop(); | 2349 image_processor_bitstream_buffer_ids_.pop(); |
| 2353 | 2350 |
| 2354 return true; | 2351 return true; |
| 2355 } | 2352 } |
| 2356 | 2353 |
| 2357 bool V4L2VideoDecodeAccelerator::CreateImageProcessor() { | 2354 bool V4L2VideoDecodeAccelerator::CreateImageProcessor() { |
| 2358 DVLOGF(3); | 2355 DVLOGF(2); |
| 2359 DCHECK(!image_processor_); | 2356 DCHECK(!image_processor_); |
| 2360 image_processor_.reset(new V4L2ImageProcessor(image_processor_device_)); | 2357 image_processor_.reset(new V4L2ImageProcessor(image_processor_device_)); |
| 2361 v4l2_memory output_memory_type = | 2358 v4l2_memory output_memory_type = |
| 2362 (output_mode_ == Config::OutputMode::ALLOCATE ? V4L2_MEMORY_MMAP | 2359 (output_mode_ == Config::OutputMode::ALLOCATE ? V4L2_MEMORY_MMAP |
| 2363 : V4L2_MEMORY_DMABUF); | 2360 : V4L2_MEMORY_DMABUF); |
| 2364 // Unretained is safe because |this| owns image processor and there will be | 2361 // Unretained is safe because |this| owns image processor and there will be |
| 2365 // no callbacks after processor destroys. | 2362 // no callbacks after processor destroys. |
| 2366 if (!image_processor_->Initialize( | 2363 if (!image_processor_->Initialize( |
| 2367 V4L2Device::V4L2PixFmtToVideoPixelFormat(output_format_fourcc_), | 2364 V4L2Device::V4L2PixFmtToVideoPixelFormat(output_format_fourcc_), |
| 2368 V4L2Device::V4L2PixFmtToVideoPixelFormat(egl_image_format_fourcc_), | 2365 V4L2Device::V4L2PixFmtToVideoPixelFormat(egl_image_format_fourcc_), |
| 2369 V4L2_MEMORY_DMABUF, output_memory_type, visible_size_, coded_size_, | 2366 V4L2_MEMORY_DMABUF, output_memory_type, visible_size_, coded_size_, |
| 2370 visible_size_, egl_image_size_, output_buffer_map_.size(), | 2367 visible_size_, egl_image_size_, output_buffer_map_.size(), |
| 2371 base::Bind(&V4L2VideoDecodeAccelerator::ImageProcessorError, | 2368 base::Bind(&V4L2VideoDecodeAccelerator::ImageProcessorError, |
| 2372 base::Unretained(this)))) { | 2369 base::Unretained(this)))) { |
| 2373 LOGF(ERROR) << "Initialize image processor failed"; | 2370 LOGF(ERROR) << "Initialize image processor failed"; |
| 2374 NOTIFY_ERROR(PLATFORM_FAILURE); | 2371 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 2375 return false; | 2372 return false; |
| 2376 } | 2373 } |
| 2377 DVLOGF(3) << "image_processor_->output_allocated_size()=" | 2374 DVLOGF(2) << "image_processor_->output_allocated_size()=" |
| 2378 << image_processor_->output_allocated_size().ToString(); | 2375 << image_processor_->output_allocated_size().ToString(); |
| 2379 DCHECK(image_processor_->output_allocated_size() == egl_image_size_); | 2376 DCHECK(image_processor_->output_allocated_size() == egl_image_size_); |
| 2380 if (image_processor_->input_allocated_size() != coded_size_) { | 2377 if (image_processor_->input_allocated_size() != coded_size_) { |
| 2381 LOGF(ERROR) << "Image processor should be able to take the output coded " | 2378 LOGF(ERROR) << "Image processor should be able to take the output coded " |
| 2382 << "size of decoder " << coded_size_.ToString() | 2379 << "size of decoder " << coded_size_.ToString() |
| 2383 << " without adjusting to " | 2380 << " without adjusting to " |
| 2384 << image_processor_->input_allocated_size().ToString(); | 2381 << image_processor_->input_allocated_size().ToString(); |
| 2385 NOTIFY_ERROR(PLATFORM_FAILURE); | 2382 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 2386 return false; | 2383 return false; |
| 2387 } | 2384 } |
| 2388 return true; | 2385 return true; |
| 2389 } | 2386 } |
| 2390 | 2387 |
| 2391 bool V4L2VideoDecodeAccelerator::ProcessFrame(int32_t bitstream_buffer_id, | 2388 bool V4L2VideoDecodeAccelerator::ProcessFrame(int32_t bitstream_buffer_id, |
| 2392 int output_buffer_index) { | 2389 int output_buffer_index) { |
| 2393 DVLOGF(3); | 2390 DVLOGF(4); |
| 2394 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 2391 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 2395 | 2392 |
| 2396 OutputRecord& output_record = output_buffer_map_[output_buffer_index]; | 2393 OutputRecord& output_record = output_buffer_map_[output_buffer_index]; |
| 2397 DCHECK_EQ(output_record.state, kAtDevice); | 2394 DCHECK_EQ(output_record.state, kAtDevice); |
| 2398 output_record.state = kAtProcessor; | 2395 output_record.state = kAtProcessor; |
| 2399 image_processor_bitstream_buffer_ids_.push(bitstream_buffer_id); | 2396 image_processor_bitstream_buffer_ids_.push(bitstream_buffer_id); |
| 2400 std::vector<int> processor_input_fds; | 2397 std::vector<int> processor_input_fds; |
| 2401 for (auto& fd : output_record.processor_input_fds) { | 2398 for (auto& fd : output_record.processor_input_fds) { |
| 2402 processor_input_fds.push_back(fd.get()); | 2399 processor_input_fds.push_back(fd.get()); |
| 2403 } | 2400 } |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 2420 // Unretained is safe because |this| owns image processor and there will | 2417 // Unretained is safe because |this| owns image processor and there will |
| 2421 // be no callbacks after processor destroys. | 2418 // be no callbacks after processor destroys. |
| 2422 image_processor_->Process( | 2419 image_processor_->Process( |
| 2423 input_frame, output_buffer_index, std::move(processor_output_fds), | 2420 input_frame, output_buffer_index, std::move(processor_output_fds), |
| 2424 base::Bind(&V4L2VideoDecodeAccelerator::FrameProcessed, | 2421 base::Bind(&V4L2VideoDecodeAccelerator::FrameProcessed, |
| 2425 base::Unretained(this), bitstream_buffer_id)); | 2422 base::Unretained(this), bitstream_buffer_id)); |
| 2426 return true; | 2423 return true; |
| 2427 } | 2424 } |
| 2428 | 2425 |
| 2429 bool V4L2VideoDecodeAccelerator::CreateOutputBuffers() { | 2426 bool V4L2VideoDecodeAccelerator::CreateOutputBuffers() { |
| 2430 DVLOGF(3); | 2427 DVLOGF(2); |
| 2431 DCHECK(decoder_state_ == kInitialized || | 2428 DCHECK(decoder_state_ == kInitialized || |
| 2432 decoder_state_ == kChangingResolution); | 2429 decoder_state_ == kChangingResolution); |
| 2433 DCHECK(!output_streamon_); | 2430 DCHECK(!output_streamon_); |
| 2434 DCHECK(output_buffer_map_.empty()); | 2431 DCHECK(output_buffer_map_.empty()); |
| 2435 | 2432 |
| 2436 // Number of output buffers we need. | 2433 // Number of output buffers we need. |
| 2437 struct v4l2_control ctrl; | 2434 struct v4l2_control ctrl; |
| 2438 memset(&ctrl, 0, sizeof(ctrl)); | 2435 memset(&ctrl, 0, sizeof(ctrl)); |
| 2439 ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE; | 2436 ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE; |
| 2440 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_G_CTRL, &ctrl); | 2437 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_G_CTRL, &ctrl); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 2468 // non-slice NALUs and could even get another resolution change before we were | 2465 // non-slice NALUs and could even get another resolution change before we were |
| 2469 // done with this one. After we get the buffers, we'll go back into kIdle and | 2466 // done with this one. After we get the buffers, we'll go back into kIdle and |
| 2470 // kick off further event processing, and eventually go back into kDecoding | 2467 // kick off further event processing, and eventually go back into kDecoding |
| 2471 // once no more events are pending (if any). | 2468 // once no more events are pending (if any). |
| 2472 decoder_state_ = kAwaitingPictureBuffers; | 2469 decoder_state_ = kAwaitingPictureBuffers; |
| 2473 | 2470 |
| 2474 return true; | 2471 return true; |
| 2475 } | 2472 } |
| 2476 | 2473 |
| 2477 void V4L2VideoDecodeAccelerator::DestroyInputBuffers() { | 2474 void V4L2VideoDecodeAccelerator::DestroyInputBuffers() { |
| 2478 DVLOGF(3); | 2475 DVLOGF(2); |
| 2479 DCHECK(!decoder_thread_.IsRunning() || | 2476 DCHECK(!decoder_thread_.IsRunning() || |
| 2480 decoder_thread_.task_runner()->BelongsToCurrentThread()); | 2477 decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 2481 DCHECK(!input_streamon_); | 2478 DCHECK(!input_streamon_); |
| 2482 | 2479 |
| 2483 if (input_buffer_map_.empty()) | 2480 if (input_buffer_map_.empty()) |
| 2484 return; | 2481 return; |
| 2485 | 2482 |
| 2486 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { | 2483 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { |
| 2487 if (input_buffer_map_[i].address != NULL) { | 2484 if (input_buffer_map_[i].address != NULL) { |
| 2488 device_->Munmap(input_buffer_map_[i].address, | 2485 device_->Munmap(input_buffer_map_[i].address, |
| 2489 input_buffer_map_[i].length); | 2486 input_buffer_map_[i].length); |
| 2490 } | 2487 } |
| 2491 } | 2488 } |
| 2492 | 2489 |
| 2493 struct v4l2_requestbuffers reqbufs; | 2490 struct v4l2_requestbuffers reqbufs; |
| 2494 memset(&reqbufs, 0, sizeof(reqbufs)); | 2491 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 2495 reqbufs.count = 0; | 2492 reqbufs.count = 0; |
| 2496 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 2493 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 2497 reqbufs.memory = V4L2_MEMORY_MMAP; | 2494 reqbufs.memory = V4L2_MEMORY_MMAP; |
| 2498 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); | 2495 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); |
| 2499 | 2496 |
| 2500 input_buffer_map_.clear(); | 2497 input_buffer_map_.clear(); |
| 2501 free_input_buffers_.clear(); | 2498 free_input_buffers_.clear(); |
| 2502 } | 2499 } |
| 2503 | 2500 |
| 2504 bool V4L2VideoDecodeAccelerator::DestroyOutputBuffers() { | 2501 bool V4L2VideoDecodeAccelerator::DestroyOutputBuffers() { |
| 2505 DVLOGF(3); | 2502 DVLOGF(2); |
| 2506 DCHECK(!decoder_thread_.IsRunning() || | 2503 DCHECK(!decoder_thread_.IsRunning() || |
| 2507 decoder_thread_.task_runner()->BelongsToCurrentThread()); | 2504 decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 2508 DCHECK(!output_streamon_); | 2505 DCHECK(!output_streamon_); |
| 2509 bool success = true; | 2506 bool success = true; |
| 2510 | 2507 |
| 2511 if (output_buffer_map_.empty()) | 2508 if (output_buffer_map_.empty()) |
| 2512 return true; | 2509 return true; |
| 2513 | 2510 |
| 2514 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { | 2511 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { |
| 2515 OutputRecord& output_record = output_buffer_map_[i]; | 2512 OutputRecord& output_record = output_buffer_map_[i]; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2550 free_output_buffers_.pop_front(); | 2547 free_output_buffers_.pop_front(); |
| 2551 output_buffer_queued_count_ = 0; | 2548 output_buffer_queued_count_ = 0; |
| 2552 // The client may still hold some buffers. The texture holds a reference to | 2549 // The client may still hold some buffers. The texture holds a reference to |
| 2553 // the buffer. It is OK to free the buffer and destroy EGLImage here. | 2550 // the buffer. It is OK to free the buffer and destroy EGLImage here. |
| 2554 decoder_frames_at_client_ = 0; | 2551 decoder_frames_at_client_ = 0; |
| 2555 | 2552 |
| 2556 return success; | 2553 return success; |
| 2557 } | 2554 } |
| 2558 | 2555 |
| 2559 void V4L2VideoDecodeAccelerator::SendPictureReady() { | 2556 void V4L2VideoDecodeAccelerator::SendPictureReady() { |
| 2560 DVLOGF(3); | 2557 DVLOGF(4); |
| 2561 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 2558 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 2562 bool send_now = (decoder_state_ == kChangingResolution || | 2559 bool send_now = (decoder_state_ == kChangingResolution || |
| 2563 decoder_state_ == kResetting || decoder_flushing_); | 2560 decoder_state_ == kResetting || decoder_flushing_); |
| 2564 while (pending_picture_ready_.size() > 0) { | 2561 while (pending_picture_ready_.size() > 0) { |
| 2565 bool cleared = pending_picture_ready_.front().cleared; | 2562 bool cleared = pending_picture_ready_.front().cleared; |
| 2566 const Picture& picture = pending_picture_ready_.front().picture; | 2563 const Picture& picture = pending_picture_ready_.front().picture; |
| 2567 if (cleared && picture_clearing_count_ == 0) { | 2564 if (cleared && picture_clearing_count_ == 0) { |
| 2568 // This picture is cleared. It can be posted to a thread different than | 2565 // This picture is cleared. It can be posted to a thread different than |
| 2569 // the main GPU thread to reduce latency. This should be the case after | 2566 // the main GPU thread to reduce latency. This should be the case after |
| 2570 // all pictures are cleared at the beginning. | 2567 // all pictures are cleared at the beginning. |
| 2571 decode_task_runner_->PostTask( | 2568 decode_task_runner_->PostTask( |
| 2572 FROM_HERE, | 2569 FROM_HERE, |
| 2573 base::Bind(&Client::PictureReady, decode_client_, picture)); | 2570 base::Bind(&Client::PictureReady, decode_client_, picture)); |
| 2574 pending_picture_ready_.pop(); | 2571 pending_picture_ready_.pop(); |
| 2575 } else if (!cleared || send_now) { | 2572 } else if (!cleared || send_now) { |
| 2576 DVLOGF(3) << "cleared=" << pending_picture_ready_.front().cleared | 2573 DVLOGF(4) << "cleared=" << pending_picture_ready_.front().cleared |
| 2577 << ", decoder_state_=" << decoder_state_ | 2574 << ", decoder_state_=" << decoder_state_ |
| 2578 << ", decoder_flushing_=" << decoder_flushing_ | 2575 << ", decoder_flushing_=" << decoder_flushing_ |
| 2579 << ", picture_clearing_count_=" << picture_clearing_count_; | 2576 << ", picture_clearing_count_=" << picture_clearing_count_; |
| 2580 // If the picture is not cleared, post it to the child thread because it | 2577 // If the picture is not cleared, post it to the child thread because it |
| 2581 // has to be cleared in the child thread. A picture only needs to be | 2578 // has to be cleared in the child thread. A picture only needs to be |
| 2582 // cleared once. If the decoder is changing resolution, resetting or | 2579 // cleared once. If the decoder is changing resolution, resetting or |
| 2583 // flushing, send all pictures to ensure PictureReady arrive before | 2580 // flushing, send all pictures to ensure PictureReady arrive before |
| 2584 // ProvidePictureBuffers, NotifyResetDone, or NotifyFlushDone. | 2581 // ProvidePictureBuffers, NotifyResetDone, or NotifyFlushDone. |
| 2585 child_task_runner_->PostTaskAndReply( | 2582 child_task_runner_->PostTaskAndReply( |
| 2586 FROM_HERE, base::Bind(&Client::PictureReady, client_, picture), | 2583 FROM_HERE, base::Bind(&Client::PictureReady, client_, picture), |
| 2587 // Unretained is safe. If Client::PictureReady gets to run, |this| is | 2584 // Unretained is safe. If Client::PictureReady gets to run, |this| is |
| 2588 // alive. Destroy() will wait the decode thread to finish. | 2585 // alive. Destroy() will wait the decode thread to finish. |
| 2589 base::Bind(&V4L2VideoDecodeAccelerator::PictureCleared, | 2586 base::Bind(&V4L2VideoDecodeAccelerator::PictureCleared, |
| 2590 base::Unretained(this))); | 2587 base::Unretained(this))); |
| 2591 picture_clearing_count_++; | 2588 picture_clearing_count_++; |
| 2592 pending_picture_ready_.pop(); | 2589 pending_picture_ready_.pop(); |
| 2593 } else { | 2590 } else { |
| 2594 // This picture is cleared. But some pictures are about to be cleared on | 2591 // This picture is cleared. But some pictures are about to be cleared on |
| 2595 // the child thread. To preserve the order, do not send this until those | 2592 // the child thread. To preserve the order, do not send this until those |
| 2596 // pictures are cleared. | 2593 // pictures are cleared. |
| 2597 break; | 2594 break; |
| 2598 } | 2595 } |
| 2599 } | 2596 } |
| 2600 } | 2597 } |
| 2601 | 2598 |
| 2602 void V4L2VideoDecodeAccelerator::PictureCleared() { | 2599 void V4L2VideoDecodeAccelerator::PictureCleared() { |
| 2603 DVLOGF(3) << "clearing count=" << picture_clearing_count_; | 2600 DVLOGF(4) << "clearing count=" << picture_clearing_count_; |
| 2604 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 2601 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 2605 DCHECK_GT(picture_clearing_count_, 0); | 2602 DCHECK_GT(picture_clearing_count_, 0); |
| 2606 picture_clearing_count_--; | 2603 picture_clearing_count_--; |
| 2607 SendPictureReady(); | 2604 SendPictureReady(); |
| 2608 } | 2605 } |
| 2609 | 2606 |
| 2610 void V4L2VideoDecodeAccelerator::FrameProcessed(int32_t bitstream_buffer_id, | 2607 void V4L2VideoDecodeAccelerator::FrameProcessed(int32_t bitstream_buffer_id, |
| 2611 int output_buffer_index) { | 2608 int output_buffer_index) { |
| 2612 DVLOGF(3) << "output_buffer_index=" << output_buffer_index | 2609 DVLOGF(4) << "output_buffer_index=" << output_buffer_index |
| 2613 << ", bitstream_buffer_id=" << bitstream_buffer_id; | 2610 << ", bitstream_buffer_id=" << bitstream_buffer_id; |
| 2614 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 2611 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 2615 DCHECK(!image_processor_bitstream_buffer_ids_.empty()); | 2612 DCHECK(!image_processor_bitstream_buffer_ids_.empty()); |
| 2616 DCHECK(image_processor_bitstream_buffer_ids_.front() == bitstream_buffer_id); | 2613 DCHECK(image_processor_bitstream_buffer_ids_.front() == bitstream_buffer_id); |
| 2617 DCHECK_GE(output_buffer_index, 0); | 2614 DCHECK_GE(output_buffer_index, 0); |
| 2618 DCHECK_LT(output_buffer_index, static_cast<int>(output_buffer_map_.size())); | 2615 DCHECK_LT(output_buffer_index, static_cast<int>(output_buffer_map_.size())); |
| 2619 | 2616 |
| 2620 OutputRecord& output_record = output_buffer_map_[output_buffer_index]; | 2617 OutputRecord& output_record = output_buffer_map_[output_buffer_index]; |
| 2621 DVLOGF(3) << "picture_id=" << output_record.picture_id; | 2618 DVLOGF(4) << "picture_id=" << output_record.picture_id; |
| 2622 DCHECK_EQ(output_record.state, kAtProcessor); | 2619 DCHECK_EQ(output_record.state, kAtProcessor); |
| 2623 DCHECK_NE(output_record.picture_id, -1); | 2620 DCHECK_NE(output_record.picture_id, -1); |
| 2624 | 2621 |
| 2625 // Send the processed frame to render. | 2622 // Send the processed frame to render. |
| 2626 output_record.state = kAtClient; | 2623 output_record.state = kAtClient; |
| 2627 decoder_frames_at_client_++; | 2624 decoder_frames_at_client_++; |
| 2628 image_processor_bitstream_buffer_ids_.pop(); | 2625 image_processor_bitstream_buffer_ids_.pop(); |
| 2629 // TODO(hubbe): Insert correct color space. http://crbug.com/647725 | 2626 // TODO(hubbe): Insert correct color space. http://crbug.com/647725 |
| 2630 const Picture picture(output_record.picture_id, bitstream_buffer_id, | 2627 const Picture picture(output_record.picture_id, bitstream_buffer_id, |
| 2631 gfx::Rect(visible_size_), gfx::ColorSpace(), false); | 2628 gfx::Rect(visible_size_), gfx::ColorSpace(), false); |
| 2632 pending_picture_ready_.push(PictureRecord(output_record.cleared, picture)); | 2629 pending_picture_ready_.push(PictureRecord(output_record.cleared, picture)); |
| 2633 SendPictureReady(); | 2630 SendPictureReady(); |
| 2634 output_record.cleared = true; | 2631 output_record.cleared = true; |
| 2635 // Flush or resolution change may be waiting image processor to finish. | 2632 // Flush or resolution change may be waiting image processor to finish. |
| 2636 if (image_processor_bitstream_buffer_ids_.empty()) { | 2633 if (image_processor_bitstream_buffer_ids_.empty()) { |
| 2637 NotifyFlushDoneIfNeeded(); | 2634 NotifyFlushDoneIfNeeded(); |
| 2638 if (decoder_state_ == kChangingResolution) | 2635 if (decoder_state_ == kChangingResolution) |
| 2639 StartResolutionChange(); | 2636 StartResolutionChange(); |
| 2640 } | 2637 } |
| 2641 } | 2638 } |
| 2642 | 2639 |
| 2643 void V4L2VideoDecodeAccelerator::ImageProcessorError() { | 2640 void V4L2VideoDecodeAccelerator::ImageProcessorError() { |
| 2644 LOGF(ERROR) << "Image processor error"; | 2641 LOGF(ERROR) << "Image processor error"; |
| 2645 NOTIFY_ERROR(PLATFORM_FAILURE); | 2642 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 2646 } | 2643 } |
| 2647 | 2644 |
| 2648 } // namespace media | 2645 } // namespace media |
| OLD | NEW |