Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1507)

Side by Side Diff: media/gpu/v4l2_video_decode_accelerator.cc

Issue 2408703002: V4L2VideoDecodeAccelerator: implement flush by VIDIOC_DECODER_CMD. (Closed)
Patch Set: add V4L2_DEC_CMD_START back because it works now Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
OLDNEW
« media/gpu/v4l2_video_decode_accelerator.h ('K') | « media/gpu/v4l2_video_decode_accelerator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698