v4l2_stateful_decoder: Address queue dependency

It is not a requirement that the OUTPUT queue be serviced
before the CAPTURE queue.  For some h.264 clips requiring
this ordering locks up the decoder waiting for an OUTPUT
queue to be dequed.

This is fixed by changing the logic to check the CAPTURE
queue even if the OUTPUT queue does not have a buffer to
dequeue.

BUG=b:222140095
TEST=tast run $DUT video.PlatformDecoding.*

Change-Id: I4085749ed8c1593125c559c44ba60cb176936c79
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/drm-tests/+/3501484
Tested-by: Fritz Koenig <frkoenig@chromium.org>
Auto-Submit: Fritz Koenig <frkoenig@chromium.org>
Reviewed-by: Justin Green <greenjustin@google.com>
Reviewed-by: Miguel Casas-Sanchez <mcasas@chromium.org>
Reviewed-by: Miguel Casas <mcasas@google.com>
Commit-Queue: Fritz Koenig <frkoenig@chromium.org>
diff --git a/v4l2_stateful_decoder.c b/v4l2_stateful_decoder.c
index d66f93b..45bace3 100644
--- a/v4l2_stateful_decoder.c
+++ b/v4l2_stateful_decoder.c
@@ -1163,85 +1163,84 @@
           break;
         }
         num_tries--;
-        continue;
-      }
-      // Successfully dequeued a buffer. Reset the |num_tries| counter.
-      num_tries = kMaxRetryCount;
+      } else {
+        // Successfully dequeued a buffer. Reset the |num_tries| counter.
+        num_tries = kMaxRetryCount;
 
-      const bool is_flag_error_set = (flags & V4L2_BUF_FLAG_ERROR) != 0;
-      const bool is_flag_last_set = (flags & V4L2_BUF_FLAG_LAST) != 0;
-      if (is_flag_last_set)
-        CAPTURE_queue->is_streaming = false;
+        const bool is_flag_error_set = (flags & V4L2_BUF_FLAG_ERROR) != 0;
+        const bool is_flag_last_set = (flags & V4L2_BUF_FLAG_LAST) != 0;
+        if (is_flag_last_set)
+          CAPTURE_queue->is_streaming = false;
 
-      // Don't use a buffer flagged with V4L2_BUF_FLAG_ERROR regardless of
-      // |bytesused| or with V4L2_BUF_FLAG_LAST and |bytesused| == 0
-      const bool ignore_buffer = is_flag_error_set ||
-        (is_flag_last_set && (bytesused == 0));
-      if (!ignore_buffer &&
-          CAPTURE_queue->displayed_frames < frames_to_decode) {
-        CAPTURE_queue->displayed_frames++;
+        // Don't use a buffer flagged with V4L2_BUF_FLAG_ERROR regardless of
+        // |bytesused| or with V4L2_BUF_FLAG_LAST and |bytesused| == 0
+        const bool ignore_buffer = is_flag_error_set ||
+          (is_flag_last_set && (bytesused == 0));
+        if (!ignore_buffer &&
+            CAPTURE_queue->displayed_frames < frames_to_decode) {
+          CAPTURE_queue->displayed_frames++;
 
-        if (process_opaque_frame_fp) {
-          int mdp_CAPTURE_queue_buffer_index = kInvalidBufferIndex;
-          assert(V4L2_MEMORY_MMAP == CAPTURE_queue->memory);
-          if (!process_opaque_frame_fp(CAPTURE_queue,
-                                       index,
-                                       mdp_OUTPUT_queue,
-                                       mdp_CAPTURE_queue,
-                                       &mdp_CAPTURE_queue_buffer_index)){
-            LOG_ERROR("Image Processor failed.");
-            return -1;
-          }
-          mdp_CAPTURE_queue->displayed_frames++;
-          if (output_file_prefix &&
-              mdp_CAPTURE_queue_buffer_index != kInvalidBufferIndex) {
-            write_frame_to_disk(output_file_prefix, mdp_CAPTURE_queue,
-                                mdp_CAPTURE_queue_buffer_index);
-          }
+          if (process_opaque_frame_fp) {
+            int mdp_CAPTURE_queue_buffer_index = kInvalidBufferIndex;
+            assert(V4L2_MEMORY_MMAP == CAPTURE_queue->memory);
+            if (!process_opaque_frame_fp(CAPTURE_queue,
+                                        index,
+                                        mdp_OUTPUT_queue,
+                                        mdp_CAPTURE_queue,
+                                        &mdp_CAPTURE_queue_buffer_index)){
+              LOG_ERROR("Image Processor failed.");
+              return -1;
+            }
+            mdp_CAPTURE_queue->displayed_frames++;
+            if (output_file_prefix &&
+                mdp_CAPTURE_queue_buffer_index != kInvalidBufferIndex) {
+              write_frame_to_disk(output_file_prefix, mdp_CAPTURE_queue,
+                                  mdp_CAPTURE_queue_buffer_index);
+            }
 
-          if (print_md5hash &&
-              mdp_CAPTURE_queue_buffer_index != kInvalidBufferIndex) {
-            compute_and_print_md5hash(
-                mdp_CAPTURE_queue->buffers[mdp_CAPTURE_queue_buffer_index]
-                    .start[0],
-                mdp_CAPTURE_queue->buffers[mdp_CAPTURE_queue_buffer_index]
-                    .length[0],
-                CAPTURE_queue->displayed_frames);
+            if (print_md5hash &&
+                mdp_CAPTURE_queue_buffer_index != kInvalidBufferIndex) {
+              compute_and_print_md5hash(
+                  mdp_CAPTURE_queue->buffers[mdp_CAPTURE_queue_buffer_index]
+                      .start[0],
+                  mdp_CAPTURE_queue->buffers[mdp_CAPTURE_queue_buffer_index]
+                      .length[0],
+                  CAPTURE_queue->displayed_frames);
+            }
+          } else {
+            if (output_file_prefix)
+              write_frame_to_disk(output_file_prefix, CAPTURE_queue, index);
+
+            if (print_md5hash)
+              map_buffers_and_calculate_md5hash(CAPTURE_queue, index);
           }
         } else {
-          if (output_file_prefix)
-            write_frame_to_disk(output_file_prefix, CAPTURE_queue, index);
-
-          if (print_md5hash)
-            map_buffers_and_calculate_md5hash(CAPTURE_queue, index);
+          LOG_DEBUG("Buffer set %s%s%s.",
+                    is_flag_error_set ? "V4L2_BUF_FLAG_ERROR" : "",
+                    (is_flag_error_set && is_flag_last_set) ? " and " : "",
+                    is_flag_last_set ? "V4L2_BUF_FLAG_LAST" : "");
         }
-      } else {
-        LOG_DEBUG("Buffer set %s%s%s.",
-                  is_flag_error_set ? "V4L2_BUF_FLAG_ERROR" : "",
-                  (is_flag_error_set && is_flag_last_set) ? " and " : "",
-                  is_flag_last_set ? "V4L2_BUF_FLAG_LAST" : "");
-      }
 
-      // When the device has decoded |frames_to_decode| displayable frames,
-      // start the drain sequence.
-      if (!ret && OUTPUT_queue->is_streaming &&
-          CAPTURE_queue->displayed_frames >= frames_to_decode) {
-        ret = initiate_drain(OUTPUT_queue);
-      }
+        // When the device has decoded |frames_to_decode| displayable frames,
+        // start the drain sequence.
+        if (!ret && OUTPUT_queue->is_streaming &&
+            CAPTURE_queue->displayed_frames >= frames_to_decode) {
+          ret = initiate_drain(OUTPUT_queue);
+        }
 
-      // Done with buffer, queue it back up unless we got V4L2_BUF_FLAG_LAST
-      if (!ret && !is_flag_last_set)
-        ret = queue_buffer_CAPTURE(CAPTURE_queue, index);
+        // Done with buffer, queue it back up unless we got V4L2_BUF_FLAG_LAST
+        if (!ret && !is_flag_last_set)
+          ret = queue_buffer_CAPTURE(CAPTURE_queue, index);
 
-      if (!ret && pending_dynamic_resolution_change && is_flag_last_set) {
-        LOG_DEBUG("Handling dynamic resolution change.");
-        pending_dynamic_resolution_change = false;
-        ret = handle_dynamic_resolution_change(gbm, CAPTURE_queue, modifier);
+        if (!ret && pending_dynamic_resolution_change && is_flag_last_set) {
+          LOG_DEBUG("Handling dynamic resolution change.");
+          pending_dynamic_resolution_change = false;
+          ret = handle_dynamic_resolution_change(gbm, CAPTURE_queue, modifier);
+        }
       }
     }
 
-    // A frame was recieved on the CAPTURE queue, that means there should
-    // now be a free OUTPUT buffer.
+    // Check the OUTPUT queue for free buffers and fill accordingly.
     if (!ret) {
       uint32_t index = 0;
       const int ret_dequeue = dequeue_buffer(OUTPUT_queue, &index, NULL,