Commit 9270ddce authored by Alexandre Courbot's avatar Alexandre Courbot Committed by Commit Bot

media/gpu/v4l2vd: support finer-grained control of queues streaming

The stateless V4L2 decoder, which was the only V4L2 decoder
supported so far, allowed both queues to be started and stopped at
the same time. This is not the case for the stateful decoder, which
need to start the input queue first, and to keep it running when
changing resolution. Add a parameter to the streaming control
methods of the V4L2VD to allow this behavior to take place, as well
as an extra method in the backend interface to let the VD know
whether it should stop the input queue or not during resolution
changes.

This decoupling of the queues means that the input queue may now
have buffers queued when we change resolution. So remove the
DCHECK() that checked against this since it is obsolete.

BUG=b:149663704
TEST=VDAtest --use_vd passes on Krane.

Change-Id: I038b61ced2f09f7d390be1716117c65c245a10bb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2235581Reviewed-by: default avatarChih-Yu Huang <akahuang@chromium.org>
Commit-Queue: Alexandre Courbot <acourbot@chromium.org>
Cr-Commit-Position: refs/heads/master@{#776507}
parent fb20c40d
......@@ -93,7 +93,7 @@ V4L2SliceVideoDecoder::~V4L2SliceVideoDecoder() {
}
// Stop and Destroy device.
StopStreamV4L2Queue();
StopStreamV4L2Queue(true);
if (input_queue_) {
input_queue_->DeallocateBuffers();
input_queue_ = nullptr;
......@@ -116,7 +116,7 @@ void V4L2SliceVideoDecoder::Initialize(const VideoDecoderConfig& config,
// Reset V4L2 device and queue if reinitializing decoder.
if (state_ != State::kUninitialized) {
if (!StopStreamV4L2Queue()) {
if (!StopStreamV4L2Queue(true)) {
std::move(init_cb).Run(StatusCode::kV4l2FailedToStopStreamQueue);
return;
}
......@@ -321,12 +321,13 @@ void V4L2SliceVideoDecoder::Reset(base::OnceClosure closure) {
// Streamoff V4L2 queues to drop input and output buffers.
// If the queues are streaming before reset, then we need to start streaming
// them after stopping.
bool is_streaming = input_queue_->IsStreaming();
if (!StopStreamV4L2Queue())
const bool is_input_streaming = input_queue_->IsStreaming();
const bool is_output_streaming = output_queue_->IsStreaming();
if (!StopStreamV4L2Queue(true))
return;
if (is_streaming) {
if (!StartStreamV4L2Queue())
if (is_input_streaming) {
if (!StartStreamV4L2Queue(is_output_streaming))
return;
}
......@@ -352,11 +353,12 @@ void V4L2SliceVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
bitstream_id);
}
bool V4L2SliceVideoDecoder::StartStreamV4L2Queue() {
bool V4L2SliceVideoDecoder::StartStreamV4L2Queue(bool start_output_queue) {
DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
DVLOGF(3);
if (!input_queue_->Streamon() || !output_queue_->Streamon()) {
if (!input_queue_->Streamon() ||
(start_output_queue && !output_queue_->Streamon())) {
VLOGF(1) << "Failed to streamon V4L2 queue.";
SetState(State::kError);
return false;
......@@ -374,7 +376,7 @@ bool V4L2SliceVideoDecoder::StartStreamV4L2Queue() {
return true;
}
bool V4L2SliceVideoDecoder::StopStreamV4L2Queue() {
bool V4L2SliceVideoDecoder::StopStreamV4L2Queue(bool stop_input_queue) {
DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
DVLOGF(3);
......@@ -384,7 +386,7 @@ bool V4L2SliceVideoDecoder::StopStreamV4L2Queue() {
}
// Streamoff input and output queue.
if (input_queue_)
if (input_queue_ && stop_input_queue)
input_queue_->Streamoff();
if (output_queue_)
output_queue_->Streamoff();
......@@ -439,7 +441,6 @@ void V4L2SliceVideoDecoder::ContinueChangeResolution(
const size_t num_output_frames) {
DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
DVLOGF(3);
DCHECK_EQ(input_queue_->QueuedBuffersCount(), 0u);
DCHECK_EQ(output_queue_->QueuedBuffersCount(), 0u);
// If we already reset, then skip it.
......@@ -455,7 +456,9 @@ void V4L2SliceVideoDecoder::ContinueChangeResolution(
num_output_frames_ = num_output_frames;
if (!StopStreamV4L2Queue())
// Stateful decoders require the input queue to keep running during resolution
// changes, but stateless ones require it to be stopped.
if (!StopStreamV4L2Queue(backend_->StopInputQueueOnResChange()))
return;
if (!output_queue_->DeallocateBuffers()) {
......@@ -488,7 +491,7 @@ void V4L2SliceVideoDecoder::ContinueChangeResolution(
return;
}
if (!StartStreamV4L2Queue()) {
if (!StartStreamV4L2Queue(true)) {
SetState(State::kError);
return;
}
......
......@@ -116,12 +116,12 @@ class MEDIA_GPU_EXPORT V4L2SliceVideoDecoder
// in VideoFramePool. Return true if the setup is successful.
bool SetupOutputFormat(const gfx::Size& size, const gfx::Rect& visible_rect);
// Start streaming V4L2 input and output queues. Attempt to start
// |device_poll_thread_| before starting streaming.
bool StartStreamV4L2Queue();
// Stop streaming V4L2 input and output queues. Stop |device_poll_thread_|
// before stopping streaming.
bool StopStreamV4L2Queue();
// Start streaming V4L2 input and (if |start_output_queue| is true) output
// queues. Attempt to start |device_poll_thread_| after streaming starts.
bool StartStreamV4L2Queue(bool start_output_queue);
// Stop streaming V4L2 output and (if |stop_input_queue| is true) input
// queues. Stop |device_poll_thread_| before stopping streaming.
bool StopStreamV4L2Queue(bool stop_input_queue);
// Try to dequeue input and output buffers from device.
void ServiceDeviceTask(bool event);
......
......@@ -88,6 +88,12 @@ class V4L2VideoDecoderBackend {
// with |status| as argument.
virtual void ClearPendingRequests(DecodeStatus status) = 0;
// Whether we should stop the input queue when changing resolution. Stateless
// decoders require this, but stateful ones need the input queue to keep
// running. Although not super elegant, this is required to express that
// difference.
virtual bool StopInputQueueOnResChange() const = 0;
protected:
V4L2VideoDecoderBackend(Client* const client,
scoped_refptr<V4L2Device> device);
......
......@@ -49,6 +49,7 @@ class V4L2StatelessVideoDecoderBackend : public V4L2VideoDecoderBackend,
const size_t num_output_frames) override;
void OnChangeResolutionDone(bool success) override;
void ClearPendingRequests(DecodeStatus status) override;
bool StopInputQueueOnResChange() const override { return true; }
// V4L2DecodeSurfaceHandler implementation.
scoped_refptr<V4L2DecodeSurface> CreateSurface() override;
......
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