Commit 95a4ab1f authored by Alexandre Courbot's avatar Alexandre Courbot Committed by Commit Bot

media/gpu/v4l2vda: support destroying before Initialize() is called

Methods called in DestroyTask() assume that the input and output queues
have been acquired. However this is only true if Initialize() has been
successfully invoked, which only happens if a V4L2 codec device has been
found. Consequently, the V4L2VDA crashes on every non-V4L2 platform.

Fix this by explicitly checking that the queues have been acquired in
the relevant methods. Also add a few DCHECK() that check our assumptions
about the presence of input and output queues to make the code sturdier.

BUG=890952
TEST=Checked that VDA unittest was passing on Eve and Hana.

Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: Ibfa39a85486330c4daa1c0d16c0051796c0011c2
Reviewed-on: https://chromium-review.googlesource.com/1256387
Commit-Queue: Alexandre Courbot <acourbot@chromium.org>
Reviewed-by: default avatarPawel Osciak <posciak@chromium.org>
Cr-Commit-Position: refs/heads/master@{#595723}
parent 76a1ed51
...@@ -337,6 +337,7 @@ void V4L2VideoDecodeAccelerator::AssignPictureBuffersTask( ...@@ -337,6 +337,7 @@ void V4L2VideoDecodeAccelerator::AssignPictureBuffersTask(
VLOGF(2); VLOGF(2);
DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
DCHECK_EQ(decoder_state_, kAwaitingPictureBuffers); DCHECK_EQ(decoder_state_, kAwaitingPictureBuffers);
DCHECK(output_queue_);
if (IsDestroyPending()) if (IsDestroyPending())
return; return;
...@@ -1099,6 +1100,7 @@ bool V4L2VideoDecodeAccelerator::AppendToInputFrame(const void* data, ...@@ -1099,6 +1100,7 @@ bool V4L2VideoDecodeAccelerator::AppendToInputFrame(const void* data,
// Try to get an available input buffer. // Try to get an available input buffer.
if (!current_input_buffer_.IsValid()) { if (!current_input_buffer_.IsValid()) {
DCHECK(decoder_current_bitstream_buffer_ != NULL); DCHECK(decoder_current_bitstream_buffer_ != NULL);
DCHECK(input_queue_);
// See if we can get more free buffers from HW. // See if we can get more free buffers from HW.
if (input_queue_->FreeBuffersCount() == 0) if (input_queue_->FreeBuffersCount() == 0)
...@@ -1176,6 +1178,8 @@ void V4L2VideoDecodeAccelerator::ServiceDeviceTask(bool event_pending) { ...@@ -1176,6 +1178,8 @@ void V4L2VideoDecodeAccelerator::ServiceDeviceTask(bool event_pending) {
DVLOGF(4); DVLOGF(4);
DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
DCHECK_NE(decoder_state_, kUninitialized); DCHECK_NE(decoder_state_, kUninitialized);
DCHECK(input_queue_);
DCHECK(output_queue_);
TRACE_EVENT0("media,gpu", "V4L2VDA::ServiceDeviceTask"); TRACE_EVENT0("media,gpu", "V4L2VDA::ServiceDeviceTask");
if (IsDestroyPending()) if (IsDestroyPending())
...@@ -1262,6 +1266,8 @@ void V4L2VideoDecodeAccelerator::Enqueue() { ...@@ -1262,6 +1266,8 @@ void V4L2VideoDecodeAccelerator::Enqueue() {
DVLOGF(4); DVLOGF(4);
DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
DCHECK_NE(decoder_state_, kUninitialized); DCHECK_NE(decoder_state_, kUninitialized);
DCHECK(input_queue_);
DCHECK(output_queue_);
TRACE_EVENT0("media,gpu", "V4L2VDA::Enqueue"); TRACE_EVENT0("media,gpu", "V4L2VDA::Enqueue");
// Drain the pipe of completed decode buffers. // Drain the pipe of completed decode buffers.
...@@ -1375,6 +1381,8 @@ void V4L2VideoDecodeAccelerator::Dequeue() { ...@@ -1375,6 +1381,8 @@ void V4L2VideoDecodeAccelerator::Dequeue() {
DVLOGF(4); DVLOGF(4);
DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
DCHECK_NE(decoder_state_, kUninitialized); DCHECK_NE(decoder_state_, kUninitialized);
DCHECK(input_queue_);
DCHECK(output_queue_);
TRACE_EVENT0("media,gpu", "V4L2VDA::Dequeue"); TRACE_EVENT0("media,gpu", "V4L2VDA::Dequeue");
while (input_queue_->QueuedBuffersCount() > 0) { while (input_queue_->QueuedBuffersCount() > 0) {
...@@ -1390,6 +1398,7 @@ void V4L2VideoDecodeAccelerator::Dequeue() { ...@@ -1390,6 +1398,7 @@ void V4L2VideoDecodeAccelerator::Dequeue() {
bool V4L2VideoDecodeAccelerator::DequeueInputBuffer() { bool V4L2VideoDecodeAccelerator::DequeueInputBuffer() {
DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
DCHECK(input_queue_);
DCHECK_GT(input_queue_->QueuedBuffersCount(), 0u); DCHECK_GT(input_queue_->QueuedBuffersCount(), 0u);
// Dequeue a completed input (VIDEO_OUTPUT) buffer, and recycle to the free // Dequeue a completed input (VIDEO_OUTPUT) buffer, and recycle to the free
...@@ -1409,6 +1418,7 @@ bool V4L2VideoDecodeAccelerator::DequeueInputBuffer() { ...@@ -1409,6 +1418,7 @@ bool V4L2VideoDecodeAccelerator::DequeueInputBuffer() {
bool V4L2VideoDecodeAccelerator::DequeueOutputBuffer() { bool V4L2VideoDecodeAccelerator::DequeueOutputBuffer() {
DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
DCHECK(output_queue_);
DCHECK_GT(output_queue_->QueuedBuffersCount(), 0u); DCHECK_GT(output_queue_->QueuedBuffersCount(), 0u);
DCHECK(output_queue_->IsStreaming()); DCHECK(output_queue_->IsStreaming());
...@@ -1494,6 +1504,7 @@ bool V4L2VideoDecodeAccelerator::EnqueueInputRecord() { ...@@ -1494,6 +1504,7 @@ bool V4L2VideoDecodeAccelerator::EnqueueInputRecord() {
} }
bool V4L2VideoDecodeAccelerator::EnqueueOutputRecord() { bool V4L2VideoDecodeAccelerator::EnqueueOutputRecord() {
DCHECK(output_queue_);
V4L2WritableBufferRef buffer = output_queue_->GetFreeBuffer(); V4L2WritableBufferRef buffer = output_queue_->GetFreeBuffer();
DCHECK(buffer.IsValid()); DCHECK(buffer.IsValid());
...@@ -1630,6 +1641,7 @@ void V4L2VideoDecodeAccelerator::FlushTask() { ...@@ -1630,6 +1641,7 @@ void V4L2VideoDecodeAccelerator::FlushTask() {
void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() {
DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
DCHECK(input_queue_);
if (!decoder_flushing_) if (!decoder_flushing_)
return; return;
...@@ -1902,7 +1914,7 @@ bool V4L2VideoDecodeAccelerator::StopDevicePoll() { ...@@ -1902,7 +1914,7 @@ bool V4L2VideoDecodeAccelerator::StopDevicePoll() {
bool V4L2VideoDecodeAccelerator::StopOutputStream() { bool V4L2VideoDecodeAccelerator::StopOutputStream() {
VLOGF(2); VLOGF(2);
if (!output_queue_->IsStreaming()) if (!output_queue_ || !output_queue_->IsStreaming())
return true; return true;
if (!output_queue_->Streamoff()) { if (!output_queue_->Streamoff()) {
...@@ -1928,7 +1940,7 @@ bool V4L2VideoDecodeAccelerator::StopOutputStream() { ...@@ -1928,7 +1940,7 @@ bool V4L2VideoDecodeAccelerator::StopOutputStream() {
bool V4L2VideoDecodeAccelerator::StopInputStream() { bool V4L2VideoDecodeAccelerator::StopInputStream() {
VLOGF(2); VLOGF(2);
if (!input_queue_->IsStreaming()) if (!input_queue_ || !input_queue_->IsStreaming())
return true; return true;
if (!input_queue_->Streamoff()) { if (!input_queue_->Streamoff()) {
...@@ -2180,6 +2192,7 @@ bool V4L2VideoDecodeAccelerator::CreateInputBuffers() { ...@@ -2180,6 +2192,7 @@ bool V4L2VideoDecodeAccelerator::CreateInputBuffers() {
DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
// We always run this as we prepare to initialize. // We always run this as we prepare to initialize.
DCHECK_EQ(decoder_state_, kInitialized); DCHECK_EQ(decoder_state_, kInitialized);
DCHECK(input_queue_);
if (input_queue_->AllocateBuffers(kInputBufferCount, V4L2_MEMORY_MMAP) == 0) { if (input_queue_->AllocateBuffers(kInputBufferCount, V4L2_MEMORY_MMAP) == 0) {
NOTIFY_ERROR(PLATFORM_FAILURE); NOTIFY_ERROR(PLATFORM_FAILURE);
...@@ -2431,6 +2444,7 @@ bool V4L2VideoDecodeAccelerator::CreateOutputBuffers() { ...@@ -2431,6 +2444,7 @@ bool V4L2VideoDecodeAccelerator::CreateOutputBuffers() {
VLOGF(2); VLOGF(2);
DCHECK(decoder_state_ == kInitialized || DCHECK(decoder_state_ == kInitialized ||
decoder_state_ == kChangingResolution); decoder_state_ == kChangingResolution);
DCHECK(output_queue_);
DCHECK(!output_queue_->IsStreaming()); DCHECK(!output_queue_->IsStreaming());
DCHECK(output_buffer_map_.empty()); DCHECK(output_buffer_map_.empty());
...@@ -2480,6 +2494,9 @@ void V4L2VideoDecodeAccelerator::DestroyInputBuffers() { ...@@ -2480,6 +2494,9 @@ void V4L2VideoDecodeAccelerator::DestroyInputBuffers() {
DCHECK(!decoder_thread_.IsRunning() || DCHECK(!decoder_thread_.IsRunning() ||
decoder_thread_.task_runner()->BelongsToCurrentThread()); decoder_thread_.task_runner()->BelongsToCurrentThread());
if (!input_queue_)
return;
input_queue_->DeallocateBuffers(); input_queue_->DeallocateBuffers();
} }
...@@ -2487,10 +2504,10 @@ bool V4L2VideoDecodeAccelerator::DestroyOutputBuffers() { ...@@ -2487,10 +2504,10 @@ bool V4L2VideoDecodeAccelerator::DestroyOutputBuffers() {
VLOGF(2); VLOGF(2);
DCHECK(!decoder_thread_.IsRunning() || DCHECK(!decoder_thread_.IsRunning() ||
decoder_thread_.task_runner()->BelongsToCurrentThread()); decoder_thread_.task_runner()->BelongsToCurrentThread());
DCHECK(!output_queue_->IsStreaming()); DCHECK(!output_queue_ || !output_queue_->IsStreaming());
bool success = true; bool success = true;
if (output_buffer_map_.empty()) if (!output_queue_ || output_buffer_map_.empty())
return true; return true;
// Release all buffers waiting for an import buffer event // Release all buffers waiting for an import buffer event
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment