| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 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 <errno.h> | 5 #include <errno.h> |
| 6 #include <fcntl.h> | 6 #include <fcntl.h> |
| 7 #include <linux/videodev2.h> | 7 #include <linux/videodev2.h> |
| 8 #include <poll.h> | 8 #include <poll.h> |
| 9 #include <string.h> | 9 #include <string.h> |
| 10 #include <sys/eventfd.h> | 10 #include <sys/eventfd.h> |
| (...skipping 1605 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1616 | 1616 |
| 1617 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); | 1617 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); |
| 1618 DCHECK(!output_record.at_device); | 1618 DCHECK(!output_record.at_device); |
| 1619 output_record.at_client = false; | 1619 output_record.at_client = false; |
| 1620 output_record.egl_sync = egl_sync_ref->egl_sync; | 1620 output_record.egl_sync = egl_sync_ref->egl_sync; |
| 1621 // Take ownership of the EGLSync. | 1621 // Take ownership of the EGLSync. |
| 1622 egl_sync_ref->egl_sync = EGL_NO_SYNC_KHR; | 1622 egl_sync_ref->egl_sync = EGL_NO_SYNC_KHR; |
| 1623 surfaces_at_display_.erase(it); | 1623 surfaces_at_display_.erase(it); |
| 1624 } | 1624 } |
| 1625 | 1625 |
| 1626 void V4L2SliceVideoDecodeAccelerator::Flush() { | 1626 void V4L2SliceVideoDecodeAccelerator::Flush(bool return_buffers) { |
| 1627 DVLOGF(3); | 1627 DVLOGF(3); |
| 1628 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 1628 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 1629 | 1629 |
| 1630 decoder_thread_task_runner_->PostTask( | 1630 decoder_thread_task_runner_->PostTask( |
| 1631 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::FlushTask, | 1631 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::FlushTask, |
| 1632 base::Unretained(this))); | 1632 base::Unretained(this), return_buffers)); |
| 1633 } | 1633 } |
| 1634 | 1634 |
| 1635 void V4L2SliceVideoDecodeAccelerator::FlushTask() { | 1635 void V4L2SliceVideoDecodeAccelerator::FlushTask(bool return_buffers) { |
| 1636 DVLOGF(3); | 1636 DVLOGF(3); |
| 1637 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 1637 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 1638 | 1638 |
| 1639 flush_return_all_buffers_ = return_buffers; |
| 1640 |
| 1639 if (!decoder_input_queue_.empty()) { | 1641 if (!decoder_input_queue_.empty()) { |
| 1640 // We are not done with pending inputs, so queue an empty buffer, | 1642 // We are not done with pending inputs, so queue an empty buffer, |
| 1641 // which - when reached - will trigger flush sequence. | 1643 // which - when reached - will trigger flush sequence. |
| 1642 decoder_input_queue_.push( | 1644 decoder_input_queue_.push( |
| 1643 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( | 1645 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( |
| 1644 io_client_, io_task_runner_, nullptr, kFlushBufferId))); | 1646 io_client_, io_task_runner_, nullptr, kFlushBufferId))); |
| 1645 return; | 1647 return; |
| 1646 } | 1648 } |
| 1647 | 1649 |
| 1648 // No more inputs pending, so just finish flushing here. | 1650 // No more inputs pending, so just finish flushing here. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1690 // respective PictureReady calls have been posted (or they have been queued on | 1692 // respective PictureReady calls have been posted (or they have been queued on |
| 1691 // pending_picture_ready_). So at this time, once we SendPictureReady(), | 1693 // pending_picture_ready_). So at this time, once we SendPictureReady(), |
| 1692 // we will have all remaining PictureReady() posted to the client and we | 1694 // we will have all remaining PictureReady() posted to the client and we |
| 1693 // can post NotifyFlushDone(). | 1695 // can post NotifyFlushDone(). |
| 1694 DCHECK(decoder_display_queue_.empty()); | 1696 DCHECK(decoder_display_queue_.empty()); |
| 1695 | 1697 |
| 1696 // Decoder should have already returned all surfaces and all surfaces are | 1698 // Decoder should have already returned all surfaces and all surfaces are |
| 1697 // out of hardware. There can be no other owners of input buffers. | 1699 // out of hardware. There can be no other owners of input buffers. |
| 1698 DCHECK_EQ(free_input_buffers_.size(), input_buffer_map_.size()); | 1700 DCHECK_EQ(free_input_buffers_.size(), input_buffer_map_.size()); |
| 1699 | 1701 |
| 1700 SendPictureReady(); | 1702 if (flush_return_all_buffers_) { |
| 1703 for (auto& output : free_output_buffers_) { |
| 1704 scoped_refptr<V4L2DecodeSurface> dec_surface = new V4L2DecodeSurface( |
| 1705 -1, -1, output, |
| 1706 base::Bind(&V4L2SliceVideoDecodeAccelerator::ReuseOutputBuffer, |
| 1707 base::Unretained(this))); |
| 1708 OutputSurface(dec_surface); |
| 1709 } |
| 1710 |
| 1711 free_output_buffers_.clear(); |
| 1712 } |
| 1701 | 1713 |
| 1702 decoder_flushing_ = false; | 1714 decoder_flushing_ = false; |
| 1715 flush_return_all_buffers_ = false; |
| 1716 |
| 1703 DVLOGF(3) << "Flush finished"; | 1717 DVLOGF(3) << "Flush finished"; |
| 1704 | 1718 |
| 1705 child_task_runner_->PostTask(FROM_HERE, | 1719 child_task_runner_->PostTask(FROM_HERE, |
| 1706 base::Bind(&Client::NotifyFlushDone, client_)); | 1720 base::Bind(&Client::NotifyFlushDone, client_)); |
| 1707 | |
| 1708 return true; | 1721 return true; |
| 1709 } | 1722 } |
| 1710 | 1723 |
| 1711 void V4L2SliceVideoDecodeAccelerator::Reset() { | 1724 void V4L2SliceVideoDecodeAccelerator::Reset() { |
| 1712 DVLOGF(3); | 1725 DVLOGF(3); |
| 1713 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 1726 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 1714 | 1727 |
| 1715 decoder_thread_task_runner_->PostTask( | 1728 decoder_thread_task_runner_->PostTask( |
| 1716 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::ResetTask, | 1729 FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::ResetTask, |
| 1717 base::Unretained(this))); | 1730 base::Unretained(this))); |
| (...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2496 surfaces_at_display_.insert(std::make_pair(output_record.picture_id, | 2509 surfaces_at_display_.insert(std::make_pair(output_record.picture_id, |
| 2497 dec_surface)).second; | 2510 dec_surface)).second; |
| 2498 DCHECK(inserted); | 2511 DCHECK(inserted); |
| 2499 | 2512 |
| 2500 DCHECK(!output_record.at_client); | 2513 DCHECK(!output_record.at_client); |
| 2501 DCHECK(!output_record.at_device); | 2514 DCHECK(!output_record.at_device); |
| 2502 DCHECK_NE(output_record.egl_image, EGL_NO_IMAGE_KHR); | 2515 DCHECK_NE(output_record.egl_image, EGL_NO_IMAGE_KHR); |
| 2503 DCHECK_NE(output_record.picture_id, -1); | 2516 DCHECK_NE(output_record.picture_id, -1); |
| 2504 output_record.at_client = true; | 2517 output_record.at_client = true; |
| 2505 | 2518 |
| 2519 // If the surface still has a sync object assigned, destroy it. This means |
| 2520 // we didn't use this buffer for decode and we did not need to wait on it |
| 2521 // before enqueuing the buffer to the device. |
| 2522 if (output_record.egl_sync != EGL_NO_SYNC_KHR) { |
| 2523 if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) { |
| 2524 LOGF(ERROR) << "eglDestroySyncKHR failed!"; |
| 2525 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 2526 return; |
| 2527 } |
| 2528 output_record.egl_sync = EGL_NO_SYNC_KHR; |
| 2529 } |
| 2530 |
| 2506 // TODO(posciak): Use visible size from decoder here instead | 2531 // TODO(posciak): Use visible size from decoder here instead |
| 2507 // (crbug.com/402760). Passing (0, 0) results in the client using the | 2532 // (crbug.com/402760). Passing (0, 0) results in the client using the |
| 2508 // visible size extracted from the container instead. | 2533 // visible size extracted from the container instead. |
| 2509 media::Picture picture(output_record.picture_id, dec_surface->bitstream_id(), | 2534 media::Picture picture(output_record.picture_id, dec_surface->bitstream_id(), |
| 2510 gfx::Rect(0, 0), false); | 2535 gfx::Rect(0, 0), false); |
| 2511 DVLOGF(3) << dec_surface->ToString() | 2536 DVLOGF(3) << dec_surface->ToString() |
| 2512 << ", bitstream_id: " << picture.bitstream_buffer_id() | 2537 << ", bitstream_id: " << picture.bitstream_buffer_id() |
| 2513 << ", picture_id: " << picture.picture_buffer_id(); | 2538 << ", picture_id: " << picture.picture_buffer_id(); |
| 2514 pending_picture_ready_.push(PictureRecord(output_record.cleared, picture)); | 2539 pending_picture_ready_.push(PictureRecord(output_record.cleared, picture)); |
| 2515 SendPictureReady(); | 2540 SendPictureReady(); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2604 V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles() { | 2629 V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles() { |
| 2605 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); | 2630 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); |
| 2606 if (!device) | 2631 if (!device) |
| 2607 return SupportedProfiles(); | 2632 return SupportedProfiles(); |
| 2608 | 2633 |
| 2609 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), | 2634 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), |
| 2610 supported_input_fourccs_); | 2635 supported_input_fourccs_); |
| 2611 } | 2636 } |
| 2612 | 2637 |
| 2613 } // namespace content | 2638 } // namespace content |
| OLD | NEW |