Index: content/common/gpu/media/v4l2_slice_video_decode_accelerator.cc |
diff --git a/content/common/gpu/media/v4l2_slice_video_decode_accelerator.cc b/content/common/gpu/media/v4l2_slice_video_decode_accelerator.cc |
index cf0ad1c41f6c051818f186e70c2f67d3966089e5..0f8acf85940526ab32d97e2713957607ee003296 100644 |
--- a/content/common/gpu/media/v4l2_slice_video_decode_accelerator.cc |
+++ b/content/common/gpu/media/v4l2_slice_video_decode_accelerator.cc |
@@ -396,7 +396,6 @@ V4L2SliceVideoDecodeAccelerator::V4L2SliceVideoDecodeAccelerator( |
video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN), |
output_format_fourcc_(0), |
state_(kUninitialized), |
- output_mode_(Config::OutputMode::ALLOCATE), |
decoder_flushing_(false), |
decoder_resetting_(false), |
surface_set_change_pending_(false), |
@@ -457,6 +456,12 @@ bool V4L2SliceVideoDecodeAccelerator::Initialize(const Config& config, |
return false; |
} |
+ if (config.flush_mode != Config::FlushMode::KEEP_OUTPUT_BUFFERS && |
+ config.flush_mode != Config::FlushMode::RETURN_OUTPUT_BUFFERS) { |
+ NOTIMPLEMENTED() << "Unsupported Config::FlushMode"; |
+ return false; |
+ } |
+ |
client_ptr_factory_.reset( |
new base::WeakPtrFactory<VideoDecodeAccelerator::Client>(client)); |
client_ = client_ptr_factory_->GetWeakPtr(); |
@@ -528,7 +533,7 @@ bool V4L2SliceVideoDecodeAccelerator::Initialize(const Config& config, |
decoder_thread_task_runner_ = decoder_thread_.task_runner(); |
state_ = kInitialized; |
- output_mode_ = config.output_mode; |
+ config_ = config; |
// InitializeTask will NOTIFY_ERROR on failure. |
decoder_thread_task_runner_->PostTask( |
@@ -929,9 +934,9 @@ void V4L2SliceVideoDecodeAccelerator::Dequeue() { |
memset(&dqbuf, 0, sizeof(dqbuf)); |
memset(&planes, 0, sizeof(planes)); |
dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
- dqbuf.memory = |
- (output_mode_ == Config::OutputMode::ALLOCATE ? V4L2_MEMORY_MMAP |
- : V4L2_MEMORY_DMABUF); |
+ dqbuf.memory = (config_.output_mode == Config::OutputMode::ALLOCATE |
+ ? V4L2_MEMORY_MMAP |
+ : V4L2_MEMORY_DMABUF); |
dqbuf.m.planes = planes; |
dqbuf.length = output_planes_count_; |
if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { |
@@ -1105,7 +1110,7 @@ bool V4L2SliceVideoDecodeAccelerator::EnqueueOutputRecord(int index) { |
memset(qbuf_planes, 0, sizeof(qbuf_planes)); |
qbuf.index = index; |
qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
- if (output_mode_ == Config::OutputMode::ALLOCATE) { |
+ if (config_.output_mode == Config::OutputMode::ALLOCATE) { |
qbuf.memory = V4L2_MEMORY_MMAP; |
} else { |
qbuf.memory = V4L2_MEMORY_DMABUF; |
@@ -1503,9 +1508,9 @@ void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffersTask( |
memset(&reqbufs, 0, sizeof(reqbufs)); |
reqbufs.count = buffers.size(); |
reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
- reqbufs.memory = |
- (output_mode_ == Config::OutputMode::ALLOCATE ? V4L2_MEMORY_MMAP |
- : V4L2_MEMORY_DMABUF); |
+ reqbufs.memory = (config_.output_mode == Config::OutputMode::ALLOCATE |
+ ? V4L2_MEMORY_MMAP |
+ : V4L2_MEMORY_DMABUF); |
IOCTL_OR_ERROR_RETURN(VIDIOC_REQBUFS, &reqbufs); |
if (reqbufs.count != buffers.size()) { |
@@ -1535,7 +1540,7 @@ void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffersTask( |
// This will remain true until ImportBufferForPicture is called, either by |
// the client, or by ourselves, if we are allocating. |
output_record.at_client = true; |
- if (output_mode_ == Config::OutputMode::ALLOCATE) { |
+ if (config_.output_mode == Config::OutputMode::ALLOCATE) { |
std::vector<base::ScopedFD> dmabuf_fds = |
std::move(device_->GetDmabufsForV4L2Buffer( |
i, output_planes_count_, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)); |
@@ -1637,7 +1642,7 @@ void V4L2SliceVideoDecodeAccelerator::AssignEGLImage( |
DCHECK(!output_record.at_device); |
output_record.egl_image = egl_image; |
- if (output_mode_ == Config::OutputMode::IMPORT) { |
+ if (config_.output_mode == Config::OutputMode::IMPORT) { |
DCHECK(output_record.dmabuf_fds.empty()); |
output_record.dmabuf_fds = std::move(*passed_dmabuf_fds); |
} |
@@ -1665,7 +1670,7 @@ void V4L2SliceVideoDecodeAccelerator::ImportBufferForPicture( |
passed_dmabuf_fds->push_back(base::ScopedFD(fd)); |
} |
- if (output_mode_ != Config::OutputMode::IMPORT) { |
+ if (config_.output_mode != Config::OutputMode::IMPORT) { |
LOGF(ERROR) << "Cannot import in non-import mode"; |
NOTIFY_ERROR(INVALID_ARGUMENT); |
return; |
@@ -1872,14 +1877,24 @@ bool V4L2SliceVideoDecodeAccelerator::FinishFlush() { |
// out of hardware. There can be no other owners of input buffers. |
DCHECK_EQ(free_input_buffers_.size(), input_buffer_map_.size()); |
- SendPictureReady(); |
+ if (config_.flush_mode == Config::FlushMode::RETURN_OUTPUT_BUFFERS) { |
+ for (auto& output : free_output_buffers_) { |
+ scoped_refptr<V4L2DecodeSurface> dec_surface = new V4L2DecodeSurface( |
+ -1, -1, output, |
+ base::Bind(&V4L2SliceVideoDecodeAccelerator::ReuseOutputBuffer, |
+ base::Unretained(this))); |
+ OutputSurface(dec_surface); |
+ } |
+ |
+ free_output_buffers_.clear(); |
+ } |
decoder_flushing_ = false; |
+ |
DVLOGF(3) << "Flush finished"; |
child_task_runner_->PostTask(FROM_HERE, |
base::Bind(&Client::NotifyFlushDone, client_)); |
- |
return true; |
} |
@@ -2675,6 +2690,18 @@ void V4L2SliceVideoDecodeAccelerator::OutputSurface( |
DCHECK_NE(output_record.picture_id, -1); |
output_record.at_client = true; |
+ // If the surface still has a sync object assigned, destroy it. This means |
+ // we didn't use this buffer for decode and we did not need to wait on it |
+ // before enqueuing the buffer to the device. |
+ if (output_record.egl_sync != EGL_NO_SYNC_KHR) { |
+ if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) { |
+ LOGF(ERROR) << "eglDestroySyncKHR failed!"; |
+ NOTIFY_ERROR(PLATFORM_FAILURE); |
+ return; |
+ } |
+ output_record.egl_sync = EGL_NO_SYNC_KHR; |
+ } |
+ |
// TODO(posciak): Use visible size from decoder here instead |
// (crbug.com/402760). Passing (0, 0) results in the client using the |
// visible size extracted from the container instead. |