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 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 157 : child_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 157 : child_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 158 decoder_thread_("V4L2DecoderThread"), | 158 decoder_thread_("V4L2DecoderThread"), |
| 159 decoder_state_(kUninitialized), | 159 decoder_state_(kUninitialized), |
| 160 output_mode_(Config::OutputMode::ALLOCATE), | 160 output_mode_(Config::OutputMode::ALLOCATE), |
| 161 device_(device), | 161 device_(device), |
| 162 decoder_delay_bitstream_buffer_id_(-1), | 162 decoder_delay_bitstream_buffer_id_(-1), |
| 163 decoder_current_input_buffer_(-1), | 163 decoder_current_input_buffer_(-1), |
| 164 decoder_decode_buffer_tasks_scheduled_(0), | 164 decoder_decode_buffer_tasks_scheduled_(0), |
| 165 decoder_frames_at_client_(0), | 165 decoder_frames_at_client_(0), |
| 166 decoder_flushing_(false), | 166 decoder_flushing_(false), |
| 167 decoder_cmd_supported_(false), | |
| 168 flush_waiting_last_output_buffer_(false), | |
| 167 reset_pending_(false), | 169 reset_pending_(false), |
| 168 decoder_partial_frame_pending_(false), | 170 decoder_partial_frame_pending_(false), |
| 169 input_streamon_(false), | 171 input_streamon_(false), |
| 170 input_buffer_queued_count_(0), | 172 input_buffer_queued_count_(0), |
| 171 output_streamon_(false), | 173 output_streamon_(false), |
| 172 output_buffer_queued_count_(0), | 174 output_buffer_queued_count_(0), |
| 173 output_dpb_size_(0), | 175 output_dpb_size_(0), |
| 174 output_planes_count_(0), | 176 output_planes_count_(0), |
| 175 picture_clearing_count_(0), | 177 picture_clearing_count_(0), |
| 176 device_poll_thread_("V4L2DevicePollThread"), | 178 device_poll_thread_("V4L2DevicePollThread"), |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 280 } | 282 } |
| 281 | 283 |
| 282 if (!CreateInputBuffers()) | 284 if (!CreateInputBuffers()) |
| 283 return false; | 285 return false; |
| 284 | 286 |
| 285 if (!decoder_thread_.Start()) { | 287 if (!decoder_thread_.Start()) { |
| 286 LOGF(ERROR) << "decoder thread failed to start"; | 288 LOGF(ERROR) << "decoder thread failed to start"; |
| 287 return false; | 289 return false; |
| 288 } | 290 } |
| 289 | 291 |
| 292 decoder_cmd_supported_ = IsDecoderCmdSupported(); | |
| 293 | |
| 290 decoder_state_ = kInitialized; | 294 decoder_state_ = kInitialized; |
| 291 output_mode_ = config.output_mode; | 295 output_mode_ = config.output_mode; |
| 292 | 296 |
| 293 // StartDevicePoll will NOTIFY_ERROR on failure, so IgnoreResult is fine here. | 297 // StartDevicePoll will NOTIFY_ERROR on failure, so IgnoreResult is fine here. |
| 294 decoder_thread_.task_runner()->PostTask( | 298 decoder_thread_.task_runner()->PostTask( |
| 295 FROM_HERE, base::Bind(base::IgnoreResult( | 299 FROM_HERE, base::Bind(base::IgnoreResult( |
| 296 &V4L2VideoDecodeAccelerator::StartDevicePoll), | 300 &V4L2VideoDecodeAccelerator::StartDevicePoll), |
| 297 base::Unretained(this))); | 301 base::Unretained(this))); |
| 298 | 302 |
| 299 return true; | 303 return true; |
| (...skipping 1086 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1386 output_record.state = kAtClient; | 1390 output_record.state = kAtClient; |
| 1387 decoder_frames_at_client_++; | 1391 decoder_frames_at_client_++; |
| 1388 // TODO(hubbe): Insert correct color space. http://crbug.com/647725 | 1392 // TODO(hubbe): Insert correct color space. http://crbug.com/647725 |
| 1389 const Picture picture(output_record.picture_id, bitstream_buffer_id, | 1393 const Picture picture(output_record.picture_id, bitstream_buffer_id, |
| 1390 gfx::Rect(visible_size_), gfx::ColorSpace(), false); | 1394 gfx::Rect(visible_size_), gfx::ColorSpace(), false); |
| 1391 pending_picture_ready_.push( | 1395 pending_picture_ready_.push( |
| 1392 PictureRecord(output_record.cleared, picture)); | 1396 PictureRecord(output_record.cleared, picture)); |
| 1393 SendPictureReady(); | 1397 SendPictureReady(); |
| 1394 output_record.cleared = true; | 1398 output_record.cleared = true; |
| 1395 } | 1399 } |
| 1400 if ((dqbuf.flags & V4L2_BUF_FLAG_LAST)) { | |
|
kcwu
2016/10/12 02:32:39
IIUC, according to https://linuxtv.org/downloads/v
wuchengli
2016/10/12 03:08:23
Will fix this.
| |
| 1401 DVLOGF(3) << "Got last output buffer. Waiting last buffer=" | |
| 1402 << flush_waiting_last_output_buffer_; | |
| 1403 if (flush_waiting_last_output_buffer_) { | |
| 1404 struct v4l2_decoder_cmd cmd; | |
| 1405 memset(&cmd, 0, sizeof(cmd)); | |
| 1406 cmd.cmd = V4L2_DEC_CMD_START; | |
| 1407 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_DECODER_CMD, &cmd); | |
| 1408 flush_waiting_last_output_buffer_ = false; | |
| 1409 } | |
| 1410 } | |
| 1396 } | 1411 } |
| 1397 return true; | 1412 return true; |
| 1398 } | 1413 } |
| 1399 | 1414 |
| 1400 bool V4L2VideoDecodeAccelerator::EnqueueInputRecord() { | 1415 bool V4L2VideoDecodeAccelerator::EnqueueInputRecord() { |
| 1401 DVLOGF(3); | 1416 DVLOGF(3); |
| 1402 DCHECK(!input_ready_queue_.empty()); | 1417 DCHECK(!input_ready_queue_.empty()); |
| 1403 | 1418 |
| 1404 // Enqueue an input (VIDEO_OUTPUT) buffer. | 1419 // Enqueue an input (VIDEO_OUTPUT) buffer. |
| 1405 const int buffer = input_ready_queue_.front(); | 1420 const int buffer = input_ready_queue_.front(); |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1537 child_task_runner_->PostTask(FROM_HERE, | 1552 child_task_runner_->PostTask(FROM_HERE, |
| 1538 base::Bind(&Client::NotifyFlushDone, client_)); | 1553 base::Bind(&Client::NotifyFlushDone, client_)); |
| 1539 return; | 1554 return; |
| 1540 } else if (decoder_state_ == kError) { | 1555 } else if (decoder_state_ == kError) { |
| 1541 DVLOGF(2) << "early out: kError state"; | 1556 DVLOGF(2) << "early out: kError state"; |
| 1542 return; | 1557 return; |
| 1543 } | 1558 } |
| 1544 | 1559 |
| 1545 // We don't support stacked flushing. | 1560 // We don't support stacked flushing. |
| 1546 DCHECK(!decoder_flushing_); | 1561 DCHECK(!decoder_flushing_); |
| 1562 DCHECK(!flush_waiting_last_output_buffer_); | |
| 1563 if (decoder_cmd_supported_) { | |
| 1564 struct v4l2_decoder_cmd cmd; | |
| 1565 memset(&cmd, 0, sizeof(cmd)); | |
| 1566 cmd.cmd = V4L2_DEC_CMD_STOP; | |
| 1567 IOCTL_OR_ERROR_RETURN(VIDIOC_DECODER_CMD, &cmd); | |
| 1568 flush_waiting_last_output_buffer_ = true; | |
| 1569 } else { | |
| 1570 // Queue up an empty buffer -- this triggers the flush. | |
| 1571 decoder_input_queue_.push( | |
| 1572 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( | |
| 1573 decode_client_, decode_task_runner_, nullptr, kFlushBufferId))); | |
| 1574 } | |
| 1575 decoder_flushing_ = true; | |
| 1547 | 1576 |
| 1548 // Queue up an empty buffer -- this triggers the flush. | |
| 1549 decoder_input_queue_.push( | |
| 1550 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( | |
| 1551 decode_client_, decode_task_runner_, nullptr, kFlushBufferId))); | |
| 1552 decoder_flushing_ = true; | |
| 1553 SendPictureReady(); // Send all pending PictureReady. | 1577 SendPictureReady(); // Send all pending PictureReady. |
| 1554 | 1578 |
| 1555 ScheduleDecodeBufferTaskIfNeeded(); | 1579 ScheduleDecodeBufferTaskIfNeeded(); |
| 1556 } | 1580 } |
| 1557 | 1581 |
| 1558 void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { | 1582 void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { |
| 1559 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1583 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 1560 if (!decoder_flushing_) | 1584 if (!decoder_flushing_) { |
| 1585 DVLOGF(3) << "Not flushing"; | |
| 1561 return; | 1586 return; |
| 1587 } | |
| 1562 | 1588 |
| 1563 // Pipeline is empty when: | 1589 // Pipeline is empty when: |
| 1564 // * Decoder input queue is empty of non-delayed buffers. | 1590 // * Decoder input queue is empty of non-delayed buffers. |
| 1565 // * There is no currently filling input buffer. | 1591 // * There is no currently filling input buffer. |
| 1566 // * Input holding queue is empty. | 1592 // * Input holding queue is empty. |
| 1567 // * All input (VIDEO_OUTPUT) buffers are returned. | 1593 // * All input (VIDEO_OUTPUT) buffers are returned. |
| 1568 // * All image processor buffers are returned. | 1594 // * All image processor buffers are returned. |
| 1569 if (!decoder_input_queue_.empty()) { | 1595 if (!decoder_input_queue_.empty()) { |
| 1570 if (decoder_input_queue_.front()->input_id != | 1596 if (decoder_input_queue_.front()->input_id != |
| 1571 decoder_delay_bitstream_buffer_id_) | 1597 decoder_delay_bitstream_buffer_id_) { |
| 1598 DVLOGF(3) << "Some decoder inputs are not queued."; | |
| 1572 return; | 1599 return; |
| 1600 } | |
| 1573 } | 1601 } |
| 1574 if (decoder_current_input_buffer_ != -1) | 1602 if (decoder_current_input_buffer_ != -1) { |
| 1603 DVLOGF(3) << "Current input buffer != -1"; | |
| 1575 return; | 1604 return; |
| 1576 if ((input_ready_queue_.size() + input_buffer_queued_count_) != 0) | 1605 } |
| 1606 if ((input_ready_queue_.size() + input_buffer_queued_count_) != 0) { | |
| 1607 DVLOGF(3) << "some input buffers are not dequeued."; | |
| 1577 return; | 1608 return; |
| 1609 } | |
| 1578 if (image_processor_bitstream_buffer_ids_.size() != 0) | 1610 if (image_processor_bitstream_buffer_ids_.size() != 0) |
| 1579 return; | 1611 return; |
| 1612 if (flush_waiting_last_output_buffer_) { | |
| 1613 DVLOGF(3) << "Waiting last output buffer"; | |
| 1614 return; | |
| 1615 } | |
| 1580 | 1616 |
| 1581 // TODO(posciak): crbug.com/270039. Exynos requires a streamoff-streamon | 1617 // TODO(posciak): crbug.com/270039. Exynos requires a streamoff-streamon |
| 1582 // sequence after flush to continue, even if we are not resetting. This would | 1618 // sequence after flush to continue, even if we are not resetting. This would |
| 1583 // make sense, because we don't really want to resume from a non-resume point | 1619 // make sense, because we don't really want to resume from a non-resume point |
| 1584 // (e.g. not from an IDR) if we are flushed. | 1620 // (e.g. not from an IDR) if we are flushed. |
| 1585 // MSE player however triggers a Flush() on chunk end, but never Reset(). One | 1621 // MSE player however triggers a Flush() on chunk end, but never Reset(). One |
| 1586 // could argue either way, or even say that Flush() is not needed/harmful when | 1622 // could argue either way, or even say that Flush() is not needed/harmful when |
| 1587 // transitioning to next chunk. | 1623 // transitioning to next chunk. |
| 1588 // For now, do the streamoff-streamon cycle to satisfy Exynos and not freeze | 1624 // For now, do the streamoff-streamon cycle to satisfy Exynos and not freeze |
| 1589 // when doing MSE. This should be harmless otherwise. | 1625 // when doing MSE. This should be harmless otherwise. |
| 1590 if (!(StopDevicePoll() && StopOutputStream() && StopInputStream())) | 1626 if (!(StopDevicePoll() && StopOutputStream() && StopInputStream())) |
| 1591 return; | 1627 return; |
| 1592 | 1628 |
| 1593 if (!StartDevicePoll()) | 1629 if (!StartDevicePoll()) |
| 1594 return; | 1630 return; |
| 1595 | 1631 |
| 1596 decoder_delay_bitstream_buffer_id_ = -1; | 1632 decoder_delay_bitstream_buffer_id_ = -1; |
| 1597 decoder_flushing_ = false; | 1633 decoder_flushing_ = false; |
| 1598 DVLOGF(3) << "returning flush"; | 1634 DVLOGF(3) << "returning flush"; |
| 1599 child_task_runner_->PostTask(FROM_HERE, | 1635 child_task_runner_->PostTask(FROM_HERE, |
| 1600 base::Bind(&Client::NotifyFlushDone, client_)); | 1636 base::Bind(&Client::NotifyFlushDone, client_)); |
| 1601 | 1637 |
| 1602 // While we were flushing, we early-outed DecodeBufferTask()s. | 1638 // While we were flushing, we early-outed DecodeBufferTask()s. |
| 1603 ScheduleDecodeBufferTaskIfNeeded(); | 1639 ScheduleDecodeBufferTaskIfNeeded(); |
| 1604 } | 1640 } |
| 1605 | 1641 |
| 1642 bool V4L2VideoDecodeAccelerator::IsDecoderCmdSupported() { | |
| 1643 struct v4l2_decoder_cmd cmd; | |
| 1644 memset(&cmd, 0, sizeof(cmd)); | |
| 1645 cmd.cmd = V4L2_DEC_CMD_START; | |
| 1646 if (device_->Ioctl(VIDIOC_TRY_DECODER_CMD, &cmd) != 0) { | |
| 1647 DVLOGF(3) "V4L2_DEC_CMD_START is not supported."; | |
| 1648 return false; | |
| 1649 } | |
| 1650 | |
| 1651 memset(&cmd, 0, sizeof(cmd)); | |
| 1652 cmd.cmd = V4L2_DEC_CMD_STOP; | |
| 1653 if (device_->Ioctl(VIDIOC_TRY_DECODER_CMD, &cmd) != 0) { | |
| 1654 DVLOGF(3) "V4L2_DEC_CMD_STOP is not supported."; | |
| 1655 return false; | |
| 1656 } | |
| 1657 | |
| 1658 return true; | |
| 1659 } | |
| 1660 | |
| 1606 void V4L2VideoDecodeAccelerator::ResetTask() { | 1661 void V4L2VideoDecodeAccelerator::ResetTask() { |
| 1607 DVLOGF(3); | 1662 DVLOGF(3); |
| 1608 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1663 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
| 1609 TRACE_EVENT0("Video Decoder", "V4L2VDA::ResetTask"); | 1664 TRACE_EVENT0("Video Decoder", "V4L2VDA::ResetTask"); |
| 1610 | 1665 |
| 1611 if (decoder_state_ == kError) { | 1666 if (decoder_state_ == kError) { |
| 1612 DVLOGF(2) << "early out: kError state"; | 1667 DVLOGF(2) << "early out: kError state"; |
| 1613 return; | 1668 return; |
| 1614 } | 1669 } |
| 1615 decoder_current_bitstream_buffer_.reset(); | 1670 decoder_current_bitstream_buffer_.reset(); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1715 StopOutputStream(); | 1770 StopOutputStream(); |
| 1716 StopInputStream(); | 1771 StopInputStream(); |
| 1717 | 1772 |
| 1718 decoder_current_bitstream_buffer_.reset(); | 1773 decoder_current_bitstream_buffer_.reset(); |
| 1719 decoder_current_input_buffer_ = -1; | 1774 decoder_current_input_buffer_ = -1; |
| 1720 decoder_decode_buffer_tasks_scheduled_ = 0; | 1775 decoder_decode_buffer_tasks_scheduled_ = 0; |
| 1721 decoder_frames_at_client_ = 0; | 1776 decoder_frames_at_client_ = 0; |
| 1722 while (!decoder_input_queue_.empty()) | 1777 while (!decoder_input_queue_.empty()) |
| 1723 decoder_input_queue_.pop(); | 1778 decoder_input_queue_.pop(); |
| 1724 decoder_flushing_ = false; | 1779 decoder_flushing_ = false; |
| 1780 flush_waiting_last_output_buffer_ = false; | |
| 1725 | 1781 |
| 1726 if (image_processor_) | 1782 if (image_processor_) |
| 1727 image_processor_.release()->Destroy(); | 1783 image_processor_.release()->Destroy(); |
| 1728 | 1784 |
| 1729 // Set our state to kError. Just in case. | 1785 // Set our state to kError. Just in case. |
| 1730 decoder_state_ = kError; | 1786 decoder_state_ = kError; |
| 1731 | 1787 |
| 1732 DestroyInputBuffers(); | 1788 DestroyInputBuffers(); |
| 1733 DestroyOutputBuffers(); | 1789 DestroyOutputBuffers(); |
| 1734 } | 1790 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1778 | 1834 |
| 1779 bool V4L2VideoDecodeAccelerator::StopOutputStream() { | 1835 bool V4L2VideoDecodeAccelerator::StopOutputStream() { |
| 1780 DVLOGF(3); | 1836 DVLOGF(3); |
| 1781 if (!output_streamon_) | 1837 if (!output_streamon_) |
| 1782 return true; | 1838 return true; |
| 1783 | 1839 |
| 1784 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1840 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1785 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMOFF, &type); | 1841 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMOFF, &type); |
| 1786 output_streamon_ = false; | 1842 output_streamon_ = false; |
| 1787 | 1843 |
| 1844 // Output stream is stopped. No need to wait the buffer anymore. | |
| 1845 flush_waiting_last_output_buffer_ = false; | |
|
kcwu
2016/10/12 02:32:39
This line won't be executed if output_streamon_ is
wuchengli
2016/10/12 03:08:23
FlushTask won't set flush_waiting_last_output_buff
| |
| 1846 | |
| 1788 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { | 1847 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { |
| 1789 // After streamoff, the device drops ownership of all buffers, even if we | 1848 // After streamoff, the device drops ownership of all buffers, even if we |
| 1790 // don't dequeue them explicitly. Some of them may still be owned by the | 1849 // don't dequeue them explicitly. Some of them may still be owned by the |
| 1791 // client however. Reuse only those that aren't. | 1850 // client however. Reuse only those that aren't. |
| 1792 OutputRecord& output_record = output_buffer_map_[i]; | 1851 OutputRecord& output_record = output_buffer_map_[i]; |
| 1793 if (output_record.state == kAtDevice) { | 1852 if (output_record.state == kAtDevice) { |
| 1794 output_record.state = kFree; | 1853 output_record.state = kFree; |
| 1795 free_output_buffers_.push_back(i); | 1854 free_output_buffers_.push_back(i); |
| 1796 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); | 1855 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); |
| 1797 } | 1856 } |
| (...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2523 StartResolutionChange(); | 2582 StartResolutionChange(); |
| 2524 } | 2583 } |
| 2525 } | 2584 } |
| 2526 | 2585 |
| 2527 void V4L2VideoDecodeAccelerator::ImageProcessorError() { | 2586 void V4L2VideoDecodeAccelerator::ImageProcessorError() { |
| 2528 LOGF(ERROR) << "Image processor error"; | 2587 LOGF(ERROR) << "Image processor error"; |
| 2529 NOTIFY_ERROR(PLATFORM_FAILURE); | 2588 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 2530 } | 2589 } |
| 2531 | 2590 |
| 2532 } // namespace media | 2591 } // namespace media |
| OLD | NEW |