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

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

Issue 2408703002: V4L2VideoDecodeAccelerator: implement flush by VIDIOC_DECODER_CMD. (Closed)
Patch Set: address Pawel and Kuang-che's comments 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
« no previous file with comments | « media/gpu/v4l2_video_decode_accelerator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_awaiting_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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 sub.type = V4L2_EVENT_SOURCE_CHANGE; 277 sub.type = V4L2_EVENT_SOURCE_CHANGE;
276 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_SUBSCRIBE_EVENT, &sub); 278 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_SUBSCRIBE_EVENT, &sub);
277 279
278 if (video_profile_ >= H264PROFILE_MIN && video_profile_ <= H264PROFILE_MAX) { 280 if (video_profile_ >= H264PROFILE_MIN && video_profile_ <= H264PROFILE_MAX) {
279 decoder_h264_parser_.reset(new H264Parser()); 281 decoder_h264_parser_.reset(new H264Parser());
280 } 282 }
281 283
282 if (!CreateInputBuffers()) 284 if (!CreateInputBuffers())
283 return false; 285 return false;
284 286
287 decoder_cmd_supported_ = IsDecoderCmdSupported();
288
285 if (!decoder_thread_.Start()) { 289 if (!decoder_thread_.Start()) {
286 LOGF(ERROR) << "decoder thread failed to start"; 290 LOGF(ERROR) << "decoder thread failed to start";
287 return false; 291 return false;
288 } 292 }
289 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(
(...skipping 920 matching lines...) Expand 10 before | Expand all | Expand 10 after
1215 1219
1216 void V4L2VideoDecodeAccelerator::Enqueue() { 1220 void V4L2VideoDecodeAccelerator::Enqueue() {
1217 DVLOGF(3); 1221 DVLOGF(3);
1218 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 1222 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
1219 DCHECK_NE(decoder_state_, kUninitialized); 1223 DCHECK_NE(decoder_state_, kUninitialized);
1220 TRACE_EVENT0("Video Decoder", "V4L2VDA::Enqueue"); 1224 TRACE_EVENT0("Video Decoder", "V4L2VDA::Enqueue");
1221 1225
1222 // Drain the pipe of completed decode buffers. 1226 // Drain the pipe of completed decode buffers.
1223 const int old_inputs_queued = input_buffer_queued_count_; 1227 const int old_inputs_queued = input_buffer_queued_count_;
1224 while (!input_ready_queue_.empty()) { 1228 while (!input_ready_queue_.empty()) {
1225 if (!EnqueueInputRecord()) 1229 const int buffer = input_ready_queue_.front();
1230 InputRecord& input_record = input_buffer_map_[buffer];
1231 if (input_record.input_id == kFlushBufferId && decoder_cmd_supported_) {
1232 // Send the flush command after all input buffers are dequeued. This makes
1233 // sure all previous resolution changes have been handled because the
1234 // driver must hold the input buffer that triggers resolution change. The
1235 // driver cannot decode data in it without new output buffers. If we send
1236 // the flush now and a queued input buffer triggers resolution change
1237 // later, the driver will send an output buffer that has
1238 // V4L2_BUF_FLAG_LAST. But some queued input buffer have not been decoded
1239 // yet. Also, V4L2VDA calls STREAMOFF and STREAMON after resolution
1240 // change. They implicitly send a V4L2_DEC_CMD_STOP and V4L2_DEC_CMD_START
1241 // to the decoder.
1242 if (input_buffer_queued_count_ == 0) {
1243 if (!SendDecoderCmdStop())
1244 return;
1245 input_ready_queue_.pop();
1246 free_input_buffers_.push_back(buffer);
1247 input_record.input_id = -1;
1248 } else {
1249 break;
1250 }
1251 } else if (!EnqueueInputRecord())
1226 return; 1252 return;
1227 } 1253 }
1228 if (old_inputs_queued == 0 && input_buffer_queued_count_ != 0) { 1254 if (old_inputs_queued == 0 && input_buffer_queued_count_ != 0) {
1229 // We just started up a previously empty queue. 1255 // We just started up a previously empty queue.
1230 // Queue state changed; signal interrupt. 1256 // Queue state changed; signal interrupt.
1231 if (!device_->SetDevicePollInterrupt()) { 1257 if (!device_->SetDevicePollInterrupt()) {
1232 PLOGF(ERROR) << "SetDevicePollInterrupt failed"; 1258 PLOGF(ERROR) << "SetDevicePollInterrupt failed";
1233 NOTIFY_ERROR(PLATFORM_FAILURE); 1259 NOTIFY_ERROR(PLATFORM_FAILURE);
1234 return; 1260 return;
1235 } 1261 }
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
1351 memset(&dqbuf, 0, sizeof(dqbuf)); 1377 memset(&dqbuf, 0, sizeof(dqbuf));
1352 memset(planes.get(), 0, sizeof(struct v4l2_plane) * output_planes_count_); 1378 memset(planes.get(), 0, sizeof(struct v4l2_plane) * output_planes_count_);
1353 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1379 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1354 dqbuf.memory = V4L2_MEMORY_MMAP; 1380 dqbuf.memory = V4L2_MEMORY_MMAP;
1355 dqbuf.m.planes = planes.get(); 1381 dqbuf.m.planes = planes.get();
1356 dqbuf.length = output_planes_count_; 1382 dqbuf.length = output_planes_count_;
1357 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { 1383 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
1358 if (errno == EAGAIN) { 1384 if (errno == EAGAIN) {
1359 // EAGAIN if we're just out of buffers to dequeue. 1385 // EAGAIN if we're just out of buffers to dequeue.
1360 return false; 1386 return false;
1387 } else if (errno == EPIPE) {
1388 DVLOGF(3) << "Got EPIPE. Last output buffer was already dequeued.";
1389 return false;
1361 } 1390 }
1362 PLOGF(ERROR) << "ioctl() failed: VIDIOC_DQBUF"; 1391 PLOGF(ERROR) << "ioctl() failed: VIDIOC_DQBUF";
1363 NOTIFY_ERROR(PLATFORM_FAILURE); 1392 NOTIFY_ERROR(PLATFORM_FAILURE);
1364 return false; 1393 return false;
1365 } 1394 }
1366 OutputRecord& output_record = output_buffer_map_[dqbuf.index]; 1395 OutputRecord& output_record = output_buffer_map_[dqbuf.index];
1367 DCHECK_EQ(output_record.state, kAtDevice); 1396 DCHECK_EQ(output_record.state, kAtDevice);
1368 DCHECK_NE(output_record.picture_id, -1); 1397 DCHECK_NE(output_record.picture_id, -1);
1369 output_buffer_queued_count_--; 1398 output_buffer_queued_count_--;
1370 if (dqbuf.m.planes[0].bytesused == 0) { 1399 if (dqbuf.m.planes[0].bytesused == 0) {
(...skipping 16 matching lines...) Expand all
1387 decoder_frames_at_client_++; 1416 decoder_frames_at_client_++;
1388 // TODO(hubbe): Insert correct color space. http://crbug.com/647725 1417 // TODO(hubbe): Insert correct color space. http://crbug.com/647725
1389 const Picture picture(output_record.picture_id, bitstream_buffer_id, 1418 const Picture picture(output_record.picture_id, bitstream_buffer_id,
1390 gfx::Rect(visible_size_), gfx::ColorSpace(), false); 1419 gfx::Rect(visible_size_), gfx::ColorSpace(), false);
1391 pending_picture_ready_.push( 1420 pending_picture_ready_.push(
1392 PictureRecord(output_record.cleared, picture)); 1421 PictureRecord(output_record.cleared, picture));
1393 SendPictureReady(); 1422 SendPictureReady();
1394 output_record.cleared = true; 1423 output_record.cleared = true;
1395 } 1424 }
1396 } 1425 }
1426 if (dqbuf.flags & V4L2_BUF_FLAG_LAST) {
1427 DVLOGF(3) << "Got last output buffer. Waiting last buffer="
1428 << flush_awaiting_last_output_buffer_;
1429 if (flush_awaiting_last_output_buffer_) {
1430 flush_awaiting_last_output_buffer_ = false;
1431 struct v4l2_decoder_cmd cmd;
1432 memset(&cmd, 0, sizeof(cmd));
1433 cmd.cmd = V4L2_DEC_CMD_START;
1434 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_DECODER_CMD, &cmd);
1435 }
1436 }
1397 return true; 1437 return true;
1398 } 1438 }
1399 1439
1400 bool V4L2VideoDecodeAccelerator::EnqueueInputRecord() { 1440 bool V4L2VideoDecodeAccelerator::EnqueueInputRecord() {
1401 DVLOGF(3); 1441 DVLOGF(3);
1402 DCHECK(!input_ready_queue_.empty()); 1442 DCHECK(!input_ready_queue_.empty());
1403 1443
1404 // Enqueue an input (VIDEO_OUTPUT) buffer. 1444 // Enqueue an input (VIDEO_OUTPUT) buffer.
1405 const int buffer = input_ready_queue_.front(); 1445 const int buffer = input_ready_queue_.front();
1406 InputRecord& input_record = input_buffer_map_[buffer]; 1446 InputRecord& input_record = input_buffer_map_[buffer];
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
1561 return; 1601 return;
1562 1602
1563 // Pipeline is empty when: 1603 // Pipeline is empty when:
1564 // * Decoder input queue is empty of non-delayed buffers. 1604 // * Decoder input queue is empty of non-delayed buffers.
1565 // * There is no currently filling input buffer. 1605 // * There is no currently filling input buffer.
1566 // * Input holding queue is empty. 1606 // * Input holding queue is empty.
1567 // * All input (VIDEO_OUTPUT) buffers are returned. 1607 // * All input (VIDEO_OUTPUT) buffers are returned.
1568 // * All image processor buffers are returned. 1608 // * All image processor buffers are returned.
1569 if (!decoder_input_queue_.empty()) { 1609 if (!decoder_input_queue_.empty()) {
1570 if (decoder_input_queue_.front()->input_id != 1610 if (decoder_input_queue_.front()->input_id !=
1571 decoder_delay_bitstream_buffer_id_) 1611 decoder_delay_bitstream_buffer_id_) {
1612 DVLOGF(3) << "Some input bitstream buffers are not queued.";
1572 return; 1613 return;
1614 }
1573 } 1615 }
1574 if (decoder_current_input_buffer_ != -1) 1616 if (decoder_current_input_buffer_ != -1) {
1617 DVLOGF(3) << "Current input buffer != -1";
1575 return; 1618 return;
1576 if ((input_ready_queue_.size() + input_buffer_queued_count_) != 0) 1619 }
1620 if ((input_ready_queue_.size() + input_buffer_queued_count_) != 0) {
1621 DVLOGF(3) << "Some input buffers are not dequeued.";
1577 return; 1622 return;
1578 if (image_processor_bitstream_buffer_ids_.size() != 0) 1623 }
1624 if (image_processor_bitstream_buffer_ids_.size() != 0) {
1625 DVLOGF(3) << "Waiting for image processor to complete.";
1579 return; 1626 return;
1627 }
1628 if (flush_awaiting_last_output_buffer_) {
1629 DVLOGF(3) << "Waiting for last output buffer.";
1630 return;
1631 }
1580 1632
1581 // TODO(posciak): crbug.com/270039. Exynos requires a streamoff-streamon 1633 // TODO(posciak): crbug.com/270039. Exynos requires a streamoff-streamon
1582 // sequence after flush to continue, even if we are not resetting. This would 1634 // 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 1635 // 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. 1636 // (e.g. not from an IDR) if we are flushed.
1585 // MSE player however triggers a Flush() on chunk end, but never Reset(). One 1637 // 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 1638 // could argue either way, or even say that Flush() is not needed/harmful when
1587 // transitioning to next chunk. 1639 // transitioning to next chunk.
1588 // For now, do the streamoff-streamon cycle to satisfy Exynos and not freeze 1640 // For now, do the streamoff-streamon cycle to satisfy Exynos and not freeze
1589 // when doing MSE. This should be harmless otherwise. 1641 // when doing MSE. This should be harmless otherwise.
1590 if (!(StopDevicePoll() && StopOutputStream() && StopInputStream())) 1642 if (!(StopDevicePoll() && StopOutputStream() && StopInputStream()))
1591 return; 1643 return;
1592 1644
1593 if (!StartDevicePoll()) 1645 if (!StartDevicePoll())
1594 return; 1646 return;
1595 1647
1596 decoder_delay_bitstream_buffer_id_ = -1; 1648 decoder_delay_bitstream_buffer_id_ = -1;
1597 decoder_flushing_ = false; 1649 decoder_flushing_ = false;
1598 DVLOGF(3) << "returning flush"; 1650 DVLOGF(3) << "returning flush";
1599 child_task_runner_->PostTask(FROM_HERE, 1651 child_task_runner_->PostTask(FROM_HERE,
1600 base::Bind(&Client::NotifyFlushDone, client_)); 1652 base::Bind(&Client::NotifyFlushDone, client_));
1601 1653
1602 // While we were flushing, we early-outed DecodeBufferTask()s. 1654 // While we were flushing, we early-outed DecodeBufferTask()s.
1603 ScheduleDecodeBufferTaskIfNeeded(); 1655 ScheduleDecodeBufferTaskIfNeeded();
1604 } 1656 }
1605 1657
1658 bool V4L2VideoDecodeAccelerator::IsDecoderCmdSupported() {
1659 // CMD_STOP should always succeed. If the decoder is started, the command can
1660 // flush it. If the decoder is stopped, the command does nothing. We use this
1661 // to know if a driver supports V4L2_DEC_CMD_STOP to flush.
1662 struct v4l2_decoder_cmd cmd;
1663 memset(&cmd, 0, sizeof(cmd));
1664 cmd.cmd = V4L2_DEC_CMD_STOP;
1665 if (device_->Ioctl(VIDIOC_TRY_DECODER_CMD, &cmd) != 0) {
1666 DVLOGF(3) "V4L2_DEC_CMD_STOP is not supported.";
1667 return false;
1668 }
1669
1670 return true;
1671 }
1672
1673 bool V4L2VideoDecodeAccelerator::SendDecoderCmdStop() {
1674 DVLOGF(2);
1675 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
1676 DCHECK(!flush_awaiting_last_output_buffer_);
1677
1678 struct v4l2_decoder_cmd cmd;
1679 memset(&cmd, 0, sizeof(cmd));
1680 cmd.cmd = V4L2_DEC_CMD_STOP;
1681 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_DECODER_CMD, &cmd);
1682 flush_awaiting_last_output_buffer_ = true;
1683
1684 return true;
1685 }
1686
1606 void V4L2VideoDecodeAccelerator::ResetTask() { 1687 void V4L2VideoDecodeAccelerator::ResetTask() {
1607 DVLOGF(3); 1688 DVLOGF(3);
1608 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 1689 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
1609 TRACE_EVENT0("Video Decoder", "V4L2VDA::ResetTask"); 1690 TRACE_EVENT0("Video Decoder", "V4L2VDA::ResetTask");
1610 1691
1611 if (decoder_state_ == kError) { 1692 if (decoder_state_ == kError) {
1612 DVLOGF(2) << "early out: kError state"; 1693 DVLOGF(2) << "early out: kError state";
1613 return; 1694 return;
1614 } 1695 }
1615 decoder_current_bitstream_buffer_.reset(); 1696 decoder_current_bitstream_buffer_.reset();
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
1778 1859
1779 bool V4L2VideoDecodeAccelerator::StopOutputStream() { 1860 bool V4L2VideoDecodeAccelerator::StopOutputStream() {
1780 DVLOGF(3); 1861 DVLOGF(3);
1781 if (!output_streamon_) 1862 if (!output_streamon_)
1782 return true; 1863 return true;
1783 1864
1784 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1865 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1785 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMOFF, &type); 1866 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMOFF, &type);
1786 output_streamon_ = false; 1867 output_streamon_ = false;
1787 1868
1869 // Output stream is stopped. No need to wait for the buffer anymore.
1870 flush_awaiting_last_output_buffer_ = false;
1871
1788 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { 1872 for (size_t i = 0; i < output_buffer_map_.size(); ++i) {
1789 // After streamoff, the device drops ownership of all buffers, even if we 1873 // 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 1874 // don't dequeue them explicitly. Some of them may still be owned by the
1791 // client however. Reuse only those that aren't. 1875 // client however. Reuse only those that aren't.
1792 OutputRecord& output_record = output_buffer_map_[i]; 1876 OutputRecord& output_record = output_buffer_map_[i];
1793 if (output_record.state == kAtDevice) { 1877 if (output_record.state == kAtDevice) {
1794 output_record.state = kFree; 1878 output_record.state = kFree;
1795 free_output_buffers_.push_back(i); 1879 free_output_buffers_.push_back(i);
1796 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); 1880 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR);
1797 } 1881 }
(...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after
2523 StartResolutionChange(); 2607 StartResolutionChange();
2524 } 2608 }
2525 } 2609 }
2526 2610
2527 void V4L2VideoDecodeAccelerator::ImageProcessorError() { 2611 void V4L2VideoDecodeAccelerator::ImageProcessorError() {
2528 LOGF(ERROR) << "Image processor error"; 2612 LOGF(ERROR) << "Image processor error";
2529 NOTIFY_ERROR(PLATFORM_FAILURE); 2613 NOTIFY_ERROR(PLATFORM_FAILURE);
2530 } 2614 }
2531 2615
2532 } // namespace media 2616 } // namespace media
OLDNEW
« no previous file with comments | « 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