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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: media/gpu/v4l2_video_decode_accelerator.cc
diff --git a/media/gpu/v4l2_video_decode_accelerator.cc b/media/gpu/v4l2_video_decode_accelerator.cc
index b4ac8a19f993babcca1d4833d9a59ce3e83dc9e4..2fa10b10a7eda1f4ab2e48e7dc2b2203ca3c842c 100644
--- a/media/gpu/v4l2_video_decode_accelerator.cc
+++ b/media/gpu/v4l2_video_decode_accelerator.cc
@@ -164,6 +164,8 @@ V4L2VideoDecodeAccelerator::V4L2VideoDecodeAccelerator(
decoder_decode_buffer_tasks_scheduled_(0),
decoder_frames_at_client_(0),
decoder_flushing_(false),
+ decoder_cmd_supported_(false),
+ flush_waiting_last_output_buffer_(false),
reset_pending_(false),
decoder_partial_frame_pending_(false),
input_streamon_(false),
@@ -287,6 +289,8 @@ bool V4L2VideoDecodeAccelerator::Initialize(const Config& config,
return false;
}
+ 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
+
decoder_state_ = kInitialized;
output_mode_ = config.output_mode;
@@ -824,7 +828,16 @@ void V4L2VideoDecodeAccelerator::DecodeBufferTask() {
kFlushBufferId)
schedule_task = FlushInputFrame();
- if (schedule_task && AppendToInputFrame(NULL, 0) && FlushInputFrame()) {
+ 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.
+ DVLOGF(2) << "sending decoder cmd to flush";
+ DCHECK(!flush_waiting_last_output_buffer_);
+ struct v4l2_decoder_cmd cmd;
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.cmd = V4L2_DEC_CMD_STOP;
+ IOCTL_OR_ERROR_RETURN(VIDIOC_DECODER_CMD, &cmd);
+ 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
+ } else if (schedule_task && AppendToInputFrame(NULL, 0) &&
+ FlushInputFrame()) {
DVLOGF(2) << "enqueued flush buffer";
decoder_partial_frame_pending_ = false;
schedule_task = true;
@@ -1359,6 +1372,10 @@ bool V4L2VideoDecodeAccelerator::DequeueOutputBuffer() {
// EAGAIN if we're just out of buffers to dequeue.
return false;
}
+ 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
+ DVLOGF(3) << "Got EPIPE. Last output buffer was already dequeued.";
+ return false;
+ }
PLOGF(ERROR) << "ioctl() failed: VIDIOC_DQBUF";
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
@@ -1394,6 +1411,17 @@ bool V4L2VideoDecodeAccelerator::DequeueOutputBuffer() {
output_record.cleared = true;
}
}
+ 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.
+ DVLOGF(3) << "Got last output buffer. Waiting last buffer="
+ << flush_waiting_last_output_buffer_;
+ 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
+ struct v4l2_decoder_cmd cmd;
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.cmd = V4L2_DEC_CMD_START;
+ IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_DECODER_CMD, &cmd);
+ 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
+ }
+ }
return true;
}
@@ -1531,8 +1559,10 @@ void V4L2VideoDecodeAccelerator::FlushTask() {
TRACE_EVENT0("Video Decoder", "V4L2VDA::FlushTask");
// Flush outstanding buffers.
- if (decoder_state_ == kInitialized) {
- // There's nothing in the pipe, so return done immediately.
+ 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.
+ // If output stream is off, output buffers are not allocated. Or the decoder
+ // is initialized, resetting or changing resolution. There's nothing in the
+ // pipe, so return done immediately.
DVLOGF(3) << "returning flush";
child_task_runner_->PostTask(FROM_HERE,
base::Bind(&Client::NotifyFlushDone, client_));
@@ -1568,15 +1598,27 @@ void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() {
// * All image processor buffers are returned.
if (!decoder_input_queue_.empty()) {
if (decoder_input_queue_.front()->input_id !=
- decoder_delay_bitstream_buffer_id_)
+ decoder_delay_bitstream_buffer_id_) {
+ DVLOGF(3) << "Some input bitstream buffers are not queued.";
return;
+ }
}
- if (decoder_current_input_buffer_ != -1)
+ if (decoder_current_input_buffer_ != -1) {
+ DVLOGF(3) << "Current input buffer != -1";
return;
- if ((input_ready_queue_.size() + input_buffer_queued_count_) != 0)
+ }
+ if ((input_ready_queue_.size() + input_buffer_queued_count_) != 0) {
+ DVLOGF(3) << "Some input buffers are not dequeued.";
return;
- if (image_processor_bitstream_buffer_ids_.size() != 0)
+ }
+ if (image_processor_bitstream_buffer_ids_.size() != 0) {
+ DVLOGF(3) << "Waiting for image processor to complete.";
return;
+ }
+ if (flush_waiting_last_output_buffer_) {
+ DVLOGF(3) << "Waiting for last output buffer.";
+ return;
+ }
// TODO(posciak): crbug.com/270039. Exynos requires a streamoff-streamon
// sequence after flush to continue, even if we are not resetting. This would
@@ -1603,6 +1645,18 @@ void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() {
ScheduleDecodeBufferTaskIfNeeded();
}
+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
+ struct v4l2_decoder_cmd cmd;
+ memset(&cmd, 0, sizeof(cmd));
+ 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.
+ if (device_->Ioctl(VIDIOC_TRY_DECODER_CMD, &cmd) != 0) {
+ DVLOGF(3) "V4L2_DEC_CMD_STOP is not supported.";
+ return false;
+ }
+
+ return true;
+}
+
void V4L2VideoDecodeAccelerator::ResetTask() {
DVLOGF(3);
DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
@@ -1722,6 +1776,7 @@ void V4L2VideoDecodeAccelerator::DestroyTask() {
while (!decoder_input_queue_.empty())
decoder_input_queue_.pop();
decoder_flushing_ = false;
+ flush_waiting_last_output_buffer_ = false;
if (image_processor_)
image_processor_.release()->Destroy();
@@ -1785,6 +1840,9 @@ bool V4L2VideoDecodeAccelerator::StopOutputStream() {
IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMOFF, &type);
output_streamon_ = false;
+ // Output stream is stopped. No need to wait the buffer anymore.
+ flush_waiting_last_output_buffer_ = false;
+
for (size_t i = 0; i < output_buffer_map_.size(); ++i) {
// After streamoff, the device drops ownership of all buffers, even if we
// don't dequeue them explicitly. Some of them may still be owned by the
« 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