Chromium Code Reviews| 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..c68371df31c9cb66cbf185a1455c7f70dd45198c 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(); |
| + |
| 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)) { |
|
kcwu
2016/10/12 02:32:39
IIUC, according to https://linuxtv.org/downloads/v
wuchengli
2016/10/12 03:08:23
Will fix this.
|
| + 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_FALSE(VIDIOC_DECODER_CMD, &cmd); |
| + 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::IsDecoderCmdSupported() { |
| + 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; |
| if (image_processor_) |
| image_processor_.release()->Destroy(); |
| @@ -1785,6 +1841,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; |
|
kcwu
2016/10/12 02:32:39
This line won't be executed if output_streamon_ is
wuchengli
2016/10/12 03:08:23
FlushTask won't set flush_waiting_last_output_buff
|
| + |
| 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 |