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..d48cc76c59dce0897d792594269a2bfbcbb7c040 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_ = DecoderCmdSupported(); |
+ |
decoder_state_ = kInitialized; |
output_mode_ = config.output_mode; |
@@ -1393,6 +1397,17 @@ bool V4L2VideoDecodeAccelerator::DequeueOutputBuffer() { |
SendPictureReady(); |
output_record.cleared = true; |
} |
+ if ((dqbuf.flags & V4L2_BUF_FLAG_LAST)) { |
+ DVLOGF(3) << "Got last output buffer. Waiting last buffer=" |
+ << flush_waiting_last_output_buffer_; |
+ if (flush_waiting_last_output_buffer_) { |
+ struct v4l2_decoder_cmd cmd; |
+ memset(&cmd, 0, sizeof(cmd)); |
+ cmd.cmd = V4L2_DEC_CMD_START; |
+ IOCTL_OR_ERROR_RETURN(VIDIOC_DECODER_CMD, &cmd); |
kcwu
2016/10/11 08:46:05
IOCTL_OR_ERROR_RETURN_FALSE.
wondering why compile
wuchengli
2016/10/11 10:30:57
Fixed.
|
+ flush_waiting_last_output_buffer_ = false; |
+ } |
+ } |
} |
return true; |
} |
@@ -1544,12 +1559,21 @@ void V4L2VideoDecodeAccelerator::FlushTask() { |
// We don't support stacked flushing. |
DCHECK(!decoder_flushing_); |
- |
- // Queue up an empty buffer -- this triggers the flush. |
- decoder_input_queue_.push( |
- linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( |
- decode_client_, decode_task_runner_, nullptr, kFlushBufferId))); |
+ DCHECK(!flush_waiting_last_output_buffer_); |
+ if (decoder_cmd_supported_) { |
+ 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; |
+ } else { |
+ // Queue up an empty buffer -- this triggers the flush. |
+ decoder_input_queue_.push( |
+ linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( |
+ decode_client_, decode_task_runner_, nullptr, kFlushBufferId))); |
+ } |
decoder_flushing_ = true; |
+ |
SendPictureReady(); // Send all pending PictureReady. |
ScheduleDecodeBufferTaskIfNeeded(); |
@@ -1557,8 +1581,10 @@ void V4L2VideoDecodeAccelerator::FlushTask() { |
void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { |
DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); |
- if (!decoder_flushing_) |
+ if (!decoder_flushing_) { |
+ DVLOGF(3) << "Not flushing"; |
return; |
+ } |
// Pipeline is empty when: |
// * Decoder input queue is empty of non-delayed buffers. |
@@ -1568,15 +1594,25 @@ 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 decoder inputs 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) |
return; |
+ if (flush_waiting_last_output_buffer_) { |
+ DVLOGF(3) << "Waiting 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 +1639,25 @@ void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { |
ScheduleDecodeBufferTaskIfNeeded(); |
} |
+bool V4L2VideoDecodeAccelerator::DecoderCmdSupported() { |
kcwu
2016/10/11 08:46:05
How about named it as IsDecoderCmdSupported() ?
wuchengli
2016/10/11 10:30:57
Done.
|
+ struct v4l2_decoder_cmd cmd; |
+ memset(&cmd, 0, sizeof(cmd)); |
+ cmd.cmd = V4L2_DEC_CMD_START; |
+ if (device_->Ioctl(VIDIOC_TRY_DECODER_CMD, &cmd) != 0) { |
+ DVLOGF(3) "V4L2_DEC_CMD_START is not supported."; |
+ return false; |
+ } |
+ |
+ memset(&cmd, 0, sizeof(cmd)); |
+ cmd.cmd = V4L2_DEC_CMD_STOP; |
+ 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 +1777,7 @@ void V4L2VideoDecodeAccelerator::DestroyTask() { |
while (!decoder_input_queue_.empty()) |
decoder_input_queue_.pop(); |
decoder_flushing_ = false; |
+ flush_waiting_last_output_buffer_ = false; |
kcwu
2016/10/11 08:46:05
I'm wondering, if it is valid to call Reset() when
wuchengli
2016/10/11 10:30:57
I cleared flush_waiting_last_output_buffer_ in Sto
|
if (image_processor_) |
image_processor_.release()->Destroy(); |