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(); | |
Pawel Osciak
2016/10/19 09:23:04
Ideally, we should try to run this on decoder_thre
wuchengli
2016/10/20 10:14:06
I've moved it before decoder_thread start. Many ot
| |
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 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
817 // This is a dummy buffer, queued to flush the pipe. Flush. | 821 // This is a dummy buffer, queued to flush the pipe. Flush. |
818 DCHECK_EQ(decoder_current_bitstream_buffer_->input_id, kFlushBufferId); | 822 DCHECK_EQ(decoder_current_bitstream_buffer_->input_id, kFlushBufferId); |
819 // Enqueue a buffer guaranteed to be empty. To do that, we flush the | 823 // Enqueue a buffer guaranteed to be empty. To do that, we flush the |
820 // current input, enqueue no data to the next frame, then flush that down. | 824 // current input, enqueue no data to the next frame, then flush that down. |
821 schedule_task = true; | 825 schedule_task = true; |
822 if (decoder_current_input_buffer_ != -1 && | 826 if (decoder_current_input_buffer_ != -1 && |
823 input_buffer_map_[decoder_current_input_buffer_].input_id != | 827 input_buffer_map_[decoder_current_input_buffer_].input_id != |
824 kFlushBufferId) | 828 kFlushBufferId) |
825 schedule_task = FlushInputFrame(); | 829 schedule_task = FlushInputFrame(); |
826 | 830 |
827 if (schedule_task && AppendToInputFrame(NULL, 0) && FlushInputFrame()) { | 831 if (decoder_cmd_supported_) { |
wuchengli
2016/10/19 08:02:08
Pawel. It looks like I need to check schedule_task
Pawel Osciak
2016/10/19 09:23:04
Yes, but probably best to separate that logic in a
wuchengli
2016/10/20 10:14:06
Done.
| |
832 DVLOGF(2) << "sending decoder cmd to flush"; | |
833 DCHECK(!flush_waiting_last_output_buffer_); | |
834 struct v4l2_decoder_cmd cmd; | |
835 memset(&cmd, 0, sizeof(cmd)); | |
836 cmd.cmd = V4L2_DEC_CMD_STOP; | |
837 IOCTL_OR_ERROR_RETURN(VIDIOC_DECODER_CMD, &cmd); | |
838 flush_waiting_last_output_buffer_ = true; | |
kcwu
2016/10/18 05:07:13
Do you need to set decoder_partial_frame_pending_=
wuchengli
2016/10/19 08:26:58
We should set decoder_partial_frame_pending_=false
| |
839 } else if (schedule_task && AppendToInputFrame(NULL, 0) && | |
840 FlushInputFrame()) { | |
828 DVLOGF(2) << "enqueued flush buffer"; | 841 DVLOGF(2) << "enqueued flush buffer"; |
829 decoder_partial_frame_pending_ = false; | 842 decoder_partial_frame_pending_ = false; |
830 schedule_task = true; | 843 schedule_task = true; |
831 } else { | 844 } else { |
832 // If we failed to enqueue the empty buffer (due to pipeline | 845 // If we failed to enqueue the empty buffer (due to pipeline |
833 // backpressure), don't advance the bitstream buffer queue, and don't | 846 // backpressure), don't advance the bitstream buffer queue, and don't |
834 // schedule the next task. This bitstream buffer queue entry will get | 847 // schedule the next task. This bitstream buffer queue entry will get |
835 // reprocessed when the pipeline frees up. | 848 // reprocessed when the pipeline frees up. |
836 schedule_task = false; | 849 schedule_task = false; |
837 } | 850 } |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1352 memset(planes.get(), 0, sizeof(struct v4l2_plane) * output_planes_count_); | 1365 memset(planes.get(), 0, sizeof(struct v4l2_plane) * output_planes_count_); |
1353 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1366 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
1354 dqbuf.memory = V4L2_MEMORY_MMAP; | 1367 dqbuf.memory = V4L2_MEMORY_MMAP; |
1355 dqbuf.m.planes = planes.get(); | 1368 dqbuf.m.planes = planes.get(); |
1356 dqbuf.length = output_planes_count_; | 1369 dqbuf.length = output_planes_count_; |
1357 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { | 1370 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { |
1358 if (errno == EAGAIN) { | 1371 if (errno == EAGAIN) { |
1359 // EAGAIN if we're just out of buffers to dequeue. | 1372 // EAGAIN if we're just out of buffers to dequeue. |
1360 return false; | 1373 return false; |
1361 } | 1374 } |
1375 if (errno == EPIPE) { | |
Pawel Osciak
2016/10/19 09:23:04
else if?
Or even if (errno == EAGAIN || errno ==
wuchengli
2016/10/20 10:14:06
Changed to else if
| |
1376 DVLOGF(3) << "Got EPIPE. Last output buffer was already dequeued."; | |
1377 return false; | |
1378 } | |
1362 PLOGF(ERROR) << "ioctl() failed: VIDIOC_DQBUF"; | 1379 PLOGF(ERROR) << "ioctl() failed: VIDIOC_DQBUF"; |
1363 NOTIFY_ERROR(PLATFORM_FAILURE); | 1380 NOTIFY_ERROR(PLATFORM_FAILURE); |
1364 return false; | 1381 return false; |
1365 } | 1382 } |
1366 OutputRecord& output_record = output_buffer_map_[dqbuf.index]; | 1383 OutputRecord& output_record = output_buffer_map_[dqbuf.index]; |
1367 DCHECK_EQ(output_record.state, kAtDevice); | 1384 DCHECK_EQ(output_record.state, kAtDevice); |
1368 DCHECK_NE(output_record.picture_id, -1); | 1385 DCHECK_NE(output_record.picture_id, -1); |
1369 output_buffer_queued_count_--; | 1386 output_buffer_queued_count_--; |
1370 if (dqbuf.m.planes[0].bytesused == 0) { | 1387 if (dqbuf.m.planes[0].bytesused == 0) { |
1371 // This is an empty output buffer returned as part of a flush. | 1388 // This is an empty output buffer returned as part of a flush. |
(...skipping 15 matching lines...) Expand all Loading... | |
1387 decoder_frames_at_client_++; | 1404 decoder_frames_at_client_++; |
1388 // TODO(hubbe): Insert correct color space. http://crbug.com/647725 | 1405 // TODO(hubbe): Insert correct color space. http://crbug.com/647725 |
1389 const Picture picture(output_record.picture_id, bitstream_buffer_id, | 1406 const Picture picture(output_record.picture_id, bitstream_buffer_id, |
1390 gfx::Rect(visible_size_), gfx::ColorSpace(), false); | 1407 gfx::Rect(visible_size_), gfx::ColorSpace(), false); |
1391 pending_picture_ready_.push( | 1408 pending_picture_ready_.push( |
1392 PictureRecord(output_record.cleared, picture)); | 1409 PictureRecord(output_record.cleared, picture)); |
1393 SendPictureReady(); | 1410 SendPictureReady(); |
1394 output_record.cleared = true; | 1411 output_record.cleared = true; |
1395 } | 1412 } |
1396 } | 1413 } |
1414 if ((dqbuf.flags & V4L2_BUF_FLAG_LAST)) { | |
Pawel Osciak
2016/10/19 09:23:04
s/((/(/
s/))/)/
wuchengli
2016/10/20 10:14:06
Done.
| |
1415 DVLOGF(3) << "Got last output buffer. Waiting last buffer=" | |
1416 << flush_waiting_last_output_buffer_; | |
1417 if (flush_waiting_last_output_buffer_) { | |
Pawel Osciak
2016/10/19 09:23:04
Would we perhaps always want to restart, even afte
wuchengli
2016/10/20 10:14:06
Your V4L2 spec doesn't way we need to do CMD_START
| |
1418 struct v4l2_decoder_cmd cmd; | |
1419 memset(&cmd, 0, sizeof(cmd)); | |
1420 cmd.cmd = V4L2_DEC_CMD_START; | |
1421 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_DECODER_CMD, &cmd); | |
1422 flush_waiting_last_output_buffer_ = false; | |
Pawel Osciak
2016/10/19 09:23:04
We could possibly set this at the beginning, since
wuchengli
2016/10/20 10:14:06
Done. It doesn't matter much because VDA will be d
| |
1423 } | |
1424 } | |
1397 return true; | 1425 return true; |
1398 } | 1426 } |
1399 | 1427 |
1400 bool V4L2VideoDecodeAccelerator::EnqueueInputRecord() { | 1428 bool V4L2VideoDecodeAccelerator::EnqueueInputRecord() { |
1401 DVLOGF(3); | 1429 DVLOGF(3); |
1402 DCHECK(!input_ready_queue_.empty()); | 1430 DCHECK(!input_ready_queue_.empty()); |
1403 | 1431 |
1404 // Enqueue an input (VIDEO_OUTPUT) buffer. | 1432 // Enqueue an input (VIDEO_OUTPUT) buffer. |
1405 const int buffer = input_ready_queue_.front(); | 1433 const int buffer = input_ready_queue_.front(); |
1406 InputRecord& input_record = input_buffer_map_[buffer]; | 1434 InputRecord& input_record = input_buffer_map_[buffer]; |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1524 // We got a buffer back, so enqueue it back. | 1552 // We got a buffer back, so enqueue it back. |
1525 Enqueue(); | 1553 Enqueue(); |
1526 } | 1554 } |
1527 | 1555 |
1528 void V4L2VideoDecodeAccelerator::FlushTask() { | 1556 void V4L2VideoDecodeAccelerator::FlushTask() { |
1529 DVLOGF(3); | 1557 DVLOGF(3); |
1530 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1558 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
1531 TRACE_EVENT0("Video Decoder", "V4L2VDA::FlushTask"); | 1559 TRACE_EVENT0("Video Decoder", "V4L2VDA::FlushTask"); |
1532 | 1560 |
1533 // Flush outstanding buffers. | 1561 // Flush outstanding buffers. |
1534 if (decoder_state_ == kInitialized) { | 1562 if (!output_streamon_) { |
kcwu
2016/10/18 05:07:13
This change sounds not good because you do somethi
wuchengli
2016/10/19 08:26:58
Done.
| |
1535 // There's nothing in the pipe, so return done immediately. | 1563 // If output stream is off, output buffers are not allocated. Or the decoder |
1564 // is initialized, resetting or changing resolution. There's nothing in the | |
1565 // pipe, so return done immediately. | |
1536 DVLOGF(3) << "returning flush"; | 1566 DVLOGF(3) << "returning flush"; |
1537 child_task_runner_->PostTask(FROM_HERE, | 1567 child_task_runner_->PostTask(FROM_HERE, |
1538 base::Bind(&Client::NotifyFlushDone, client_)); | 1568 base::Bind(&Client::NotifyFlushDone, client_)); |
1539 return; | 1569 return; |
1540 } else if (decoder_state_ == kError) { | 1570 } else if (decoder_state_ == kError) { |
1541 DVLOGF(2) << "early out: kError state"; | 1571 DVLOGF(2) << "early out: kError state"; |
1542 return; | 1572 return; |
1543 } | 1573 } |
1544 | 1574 |
1545 // We don't support stacked flushing. | 1575 // We don't support stacked flushing. |
1546 DCHECK(!decoder_flushing_); | 1576 DCHECK(!decoder_flushing_); |
1547 | 1577 |
1548 // Queue up an empty buffer -- this triggers the flush. | 1578 // Queue up an empty buffer -- this triggers the flush. |
wuchengli
2016/10/18 02:04:51
I found we could not do CMD_STOP here because we n
Pawel Osciak
2016/10/19 09:23:04
Perhaps it would be useful to add a comment about
wuchengli
2016/10/20 10:14:06
Explained in Enqueue.
| |
1549 decoder_input_queue_.push( | 1579 decoder_input_queue_.push( |
1550 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( | 1580 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( |
1551 decode_client_, decode_task_runner_, nullptr, kFlushBufferId))); | 1581 decode_client_, decode_task_runner_, nullptr, kFlushBufferId))); |
1552 decoder_flushing_ = true; | 1582 decoder_flushing_ = true; |
1553 SendPictureReady(); // Send all pending PictureReady. | 1583 SendPictureReady(); // Send all pending PictureReady. |
1554 | 1584 |
1555 ScheduleDecodeBufferTaskIfNeeded(); | 1585 ScheduleDecodeBufferTaskIfNeeded(); |
1556 } | 1586 } |
1557 | 1587 |
1558 void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { | 1588 void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { |
1559 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1589 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
1560 if (!decoder_flushing_) | 1590 if (!decoder_flushing_) |
1561 return; | 1591 return; |
1562 | 1592 |
1563 // Pipeline is empty when: | 1593 // Pipeline is empty when: |
1564 // * Decoder input queue is empty of non-delayed buffers. | 1594 // * Decoder input queue is empty of non-delayed buffers. |
1565 // * There is no currently filling input buffer. | 1595 // * There is no currently filling input buffer. |
1566 // * Input holding queue is empty. | 1596 // * Input holding queue is empty. |
1567 // * All input (VIDEO_OUTPUT) buffers are returned. | 1597 // * All input (VIDEO_OUTPUT) buffers are returned. |
1568 // * All image processor buffers are returned. | 1598 // * All image processor buffers are returned. |
1569 if (!decoder_input_queue_.empty()) { | 1599 if (!decoder_input_queue_.empty()) { |
1570 if (decoder_input_queue_.front()->input_id != | 1600 if (decoder_input_queue_.front()->input_id != |
1571 decoder_delay_bitstream_buffer_id_) | 1601 decoder_delay_bitstream_buffer_id_) { |
1602 DVLOGF(3) << "Some input bitstream buffers are not queued."; | |
1572 return; | 1603 return; |
1604 } | |
1573 } | 1605 } |
1574 if (decoder_current_input_buffer_ != -1) | 1606 if (decoder_current_input_buffer_ != -1) { |
1607 DVLOGF(3) << "Current input buffer != -1"; | |
1575 return; | 1608 return; |
1576 if ((input_ready_queue_.size() + input_buffer_queued_count_) != 0) | 1609 } |
1610 if ((input_ready_queue_.size() + input_buffer_queued_count_) != 0) { | |
1611 DVLOGF(3) << "Some input buffers are not dequeued."; | |
1577 return; | 1612 return; |
1578 if (image_processor_bitstream_buffer_ids_.size() != 0) | 1613 } |
1614 if (image_processor_bitstream_buffer_ids_.size() != 0) { | |
1615 DVLOGF(3) << "Waiting for image processor to complete."; | |
1579 return; | 1616 return; |
1617 } | |
1618 if (flush_waiting_last_output_buffer_) { | |
1619 DVLOGF(3) << "Waiting for last output buffer."; | |
1620 return; | |
1621 } | |
1580 | 1622 |
1581 // TODO(posciak): crbug.com/270039. Exynos requires a streamoff-streamon | 1623 // TODO(posciak): crbug.com/270039. Exynos requires a streamoff-streamon |
1582 // sequence after flush to continue, even if we are not resetting. This would | 1624 // 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 | 1625 // 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. | 1626 // (e.g. not from an IDR) if we are flushed. |
1585 // MSE player however triggers a Flush() on chunk end, but never Reset(). One | 1627 // 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 | 1628 // could argue either way, or even say that Flush() is not needed/harmful when |
1587 // transitioning to next chunk. | 1629 // transitioning to next chunk. |
1588 // For now, do the streamoff-streamon cycle to satisfy Exynos and not freeze | 1630 // For now, do the streamoff-streamon cycle to satisfy Exynos and not freeze |
1589 // when doing MSE. This should be harmless otherwise. | 1631 // when doing MSE. This should be harmless otherwise. |
1590 if (!(StopDevicePoll() && StopOutputStream() && StopInputStream())) | 1632 if (!(StopDevicePoll() && StopOutputStream() && StopInputStream())) |
1591 return; | 1633 return; |
1592 | 1634 |
1593 if (!StartDevicePoll()) | 1635 if (!StartDevicePoll()) |
1594 return; | 1636 return; |
1595 | 1637 |
1596 decoder_delay_bitstream_buffer_id_ = -1; | 1638 decoder_delay_bitstream_buffer_id_ = -1; |
1597 decoder_flushing_ = false; | 1639 decoder_flushing_ = false; |
1598 DVLOGF(3) << "returning flush"; | 1640 DVLOGF(3) << "returning flush"; |
1599 child_task_runner_->PostTask(FROM_HERE, | 1641 child_task_runner_->PostTask(FROM_HERE, |
1600 base::Bind(&Client::NotifyFlushDone, client_)); | 1642 base::Bind(&Client::NotifyFlushDone, client_)); |
1601 | 1643 |
1602 // While we were flushing, we early-outed DecodeBufferTask()s. | 1644 // While we were flushing, we early-outed DecodeBufferTask()s. |
1603 ScheduleDecodeBufferTaskIfNeeded(); | 1645 ScheduleDecodeBufferTaskIfNeeded(); |
1604 } | 1646 } |
1605 | 1647 |
1648 bool V4L2VideoDecodeAccelerator::IsDecoderCmdSupported() { | |
Pawel Osciak
2016/10/19 09:23:04
Could we DCHECK we are on decoder thread here?
wuchengli
2016/10/20 10:14:06
Explained in the above comment. This still runs in
| |
1649 struct v4l2_decoder_cmd cmd; | |
1650 memset(&cmd, 0, sizeof(cmd)); | |
1651 cmd.cmd = V4L2_DEC_CMD_STOP; | |
kcwu
2016/10/17 16:24:52
Do you need to add CMD_START back?
wuchengli
2016/10/18 02:04:51
No. I found VIDIOC_TRY_DECODER_CMD didn't mean if
kcwu
2016/10/18 05:07:13
I don't fully understand. Do you mean we can try C
wuchengli
2016/10/19 08:26:58
That's right.
| |
1652 if (device_->Ioctl(VIDIOC_TRY_DECODER_CMD, &cmd) != 0) { | |
1653 DVLOGF(3) "V4L2_DEC_CMD_STOP is not supported."; | |
1654 return false; | |
1655 } | |
1656 | |
1657 return true; | |
1658 } | |
1659 | |
1606 void V4L2VideoDecodeAccelerator::ResetTask() { | 1660 void V4L2VideoDecodeAccelerator::ResetTask() { |
1607 DVLOGF(3); | 1661 DVLOGF(3); |
1608 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | 1662 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
1609 TRACE_EVENT0("Video Decoder", "V4L2VDA::ResetTask"); | 1663 TRACE_EVENT0("Video Decoder", "V4L2VDA::ResetTask"); |
1610 | 1664 |
1611 if (decoder_state_ == kError) { | 1665 if (decoder_state_ == kError) { |
1612 DVLOGF(2) << "early out: kError state"; | 1666 DVLOGF(2) << "early out: kError state"; |
1613 return; | 1667 return; |
1614 } | 1668 } |
1615 decoder_current_bitstream_buffer_.reset(); | 1669 decoder_current_bitstream_buffer_.reset(); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1715 StopOutputStream(); | 1769 StopOutputStream(); |
1716 StopInputStream(); | 1770 StopInputStream(); |
1717 | 1771 |
1718 decoder_current_bitstream_buffer_.reset(); | 1772 decoder_current_bitstream_buffer_.reset(); |
1719 decoder_current_input_buffer_ = -1; | 1773 decoder_current_input_buffer_ = -1; |
1720 decoder_decode_buffer_tasks_scheduled_ = 0; | 1774 decoder_decode_buffer_tasks_scheduled_ = 0; |
1721 decoder_frames_at_client_ = 0; | 1775 decoder_frames_at_client_ = 0; |
1722 while (!decoder_input_queue_.empty()) | 1776 while (!decoder_input_queue_.empty()) |
1723 decoder_input_queue_.pop(); | 1777 decoder_input_queue_.pop(); |
1724 decoder_flushing_ = false; | 1778 decoder_flushing_ = false; |
1779 flush_waiting_last_output_buffer_ = false; | |
1725 | 1780 |
1726 if (image_processor_) | 1781 if (image_processor_) |
1727 image_processor_.release()->Destroy(); | 1782 image_processor_.release()->Destroy(); |
1728 | 1783 |
1729 // Set our state to kError. Just in case. | 1784 // Set our state to kError. Just in case. |
1730 decoder_state_ = kError; | 1785 decoder_state_ = kError; |
1731 | 1786 |
1732 DestroyInputBuffers(); | 1787 DestroyInputBuffers(); |
1733 DestroyOutputBuffers(); | 1788 DestroyOutputBuffers(); |
1734 } | 1789 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1778 | 1833 |
1779 bool V4L2VideoDecodeAccelerator::StopOutputStream() { | 1834 bool V4L2VideoDecodeAccelerator::StopOutputStream() { |
1780 DVLOGF(3); | 1835 DVLOGF(3); |
1781 if (!output_streamon_) | 1836 if (!output_streamon_) |
1782 return true; | 1837 return true; |
1783 | 1838 |
1784 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1839 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
1785 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMOFF, &type); | 1840 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMOFF, &type); |
1786 output_streamon_ = false; | 1841 output_streamon_ = false; |
1787 | 1842 |
1843 // Output stream is stopped. No need to wait the buffer anymore. | |
1844 flush_waiting_last_output_buffer_ = false; | |
1845 | |
1788 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { | 1846 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { |
1789 // After streamoff, the device drops ownership of all buffers, even if we | 1847 // 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 | 1848 // don't dequeue them explicitly. Some of them may still be owned by the |
1791 // client however. Reuse only those that aren't. | 1849 // client however. Reuse only those that aren't. |
1792 OutputRecord& output_record = output_buffer_map_[i]; | 1850 OutputRecord& output_record = output_buffer_map_[i]; |
1793 if (output_record.state == kAtDevice) { | 1851 if (output_record.state == kAtDevice) { |
1794 output_record.state = kFree; | 1852 output_record.state = kFree; |
1795 free_output_buffers_.push_back(i); | 1853 free_output_buffers_.push_back(i); |
1796 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); | 1854 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); |
1797 } | 1855 } |
(...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2523 StartResolutionChange(); | 2581 StartResolutionChange(); |
2524 } | 2582 } |
2525 } | 2583 } |
2526 | 2584 |
2527 void V4L2VideoDecodeAccelerator::ImageProcessorError() { | 2585 void V4L2VideoDecodeAccelerator::ImageProcessorError() { |
2528 LOGF(ERROR) << "Image processor error"; | 2586 LOGF(ERROR) << "Image processor error"; |
2529 NOTIFY_ERROR(PLATFORM_FAILURE); | 2587 NOTIFY_ERROR(PLATFORM_FAILURE); |
2530 } | 2588 } |
2531 | 2589 |
2532 } // namespace media | 2590 } // namespace media |
OLD | NEW |