Commit 92531ff9 authored by David Staessens's avatar David Staessens Committed by Commit Bot

media/gpu/vaapi: Implement VaapiVideoDecoder.

This CL introduces the VaapiVideoDecoder, based on the media::VideoDecoder
interface. This decoder is a complete rewrite of the VaapiVideoDecodeAccelerator
which is based on the deprecated media::VideoDecodeAccelerator interface.

TEST=ran new VDA tests on eve

BUG=920058

Cq-Depend: chromium:1535514
Change-Id: Ib11f22afbd06c9469275aa26a3cebd04e0a4e03f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1634030
Commit-Queue: David Staessens <dstaessens@chromium.org>
Reviewed-by: default avatarAlexandre Courbot <acourbot@chromium.org>
Reviewed-by: default avatarHirokazu Honda <hiroh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#669944}
parent 36c3b10c
......@@ -24,6 +24,10 @@ source_set("linux") {
"//media/gpu:common",
]
if (use_vaapi) {
deps += [ "//media/gpu/vaapi" ]
}
if (use_v4l2_codec) {
deps += [ "//media/gpu/v4l2" ]
}
......
......@@ -12,6 +12,10 @@
#include "media/gpu/linux/mailbox_video_frame_converter.h"
#include "media/gpu/linux/platform_video_frame_pool.h"
#if BUILDFLAG(USE_VAAPI)
#include "media/gpu/vaapi/vaapi_video_decoder.h"
#endif
#if BUILDFLAG(USE_V4L2_CODEC)
#include "media/gpu/v4l2/v4l2_slice_video_decoder.h"
#endif
......@@ -27,7 +31,14 @@ std::unique_ptr<VideoDecoder> CreateLinuxVideoDecoder(
if (!client_task_runner || !frame_pool || !frame_converter)
return nullptr;
#if BUILDFLAG(USE_V4L2_CODEC)
// TODO(dstaessens@): We first try VAAPI as USE_V4L2_CODEC might also be
// set, even though initialization of V4L2SliceVideoDecoder would fail. We
// need to implement a better way to select the correct decoder.
#if BUILDFLAG(USE_VAAPI)
return VaapiVideoDecoder::Create(std::move(client_task_runner),
std::move(frame_pool),
std::move(frame_converter));
#elif BUILDFLAG(USE_V4L2_CODEC)
return V4L2SliceVideoDecoder::Create(std::move(client_task_runner),
std::move(frame_pool),
std::move(frame_converter));
......
......@@ -57,6 +57,8 @@ source_set("vaapi") {
"vaapi_utils.h",
"vaapi_video_decode_accelerator.cc",
"vaapi_video_decode_accelerator.h",
"vaapi_video_decoder.cc",
"vaapi_video_decoder.h",
"vaapi_video_encode_accelerator.cc",
"vaapi_video_encode_accelerator.h",
"vaapi_vp8_accelerator.cc",
......@@ -81,7 +83,7 @@ source_set("vaapi") {
"//media",
"//media/gpu:common",
"//media/gpu:video_frame_mapper_common",
"//media/gpu/linux",
"//media/gpu/linux:common",
"//media/parsers",
"//mojo/public/cpp/bindings",
"//third_party/libyuv",
......
This diff is collapsed.
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_VAAPI_VAAPI_VIDEO_DECODER_H_
#define MEDIA_GPU_VAAPI_VAAPI_VIDEO_DECODER_H_
#include <stdint.h>
#include <va/va.h>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include "base/containers/queue.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/threading/thread.h"
#include "media/base/video_codecs.h"
#include "media/base/video_decoder.h"
#include "media/gpu/decode_surface_handler.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
namespace media {
class AcceleratedVideoDecoder;
class DmabufVideoFramePool;
class VaapiPictureFactory;
class VaapiPicture;
class VaapiWrapper;
class VideoFrame;
class VideoFrameConverter;
class VASurface;
class VaapiVideoDecoder : public media::VideoDecoder,
public DecodeSurfaceHandler<VASurface> {
public:
static std::unique_ptr<VideoDecoder> Create(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
std::unique_ptr<DmabufVideoFramePool> frame_pool,
std::unique_ptr<VideoFrameConverter> frame_converter);
// media::VideoDecoder implementation.
std::string GetDisplayName() const override;
bool IsPlatformDecoder() const override;
bool NeedsBitstreamConversion() const override;
bool CanReadWithoutStalling() const override;
int GetMaxDecodeRequests() const override;
void Initialize(const VideoDecoderConfig& config,
bool low_delay,
CdmContext* cdm_context,
InitCB init_cb,
const OutputCB& output_cb,
const WaitingCB& waiting_cb) override;
void Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb) override;
void Reset(base::OnceClosure reset_cb) override;
// DecodeSurfaceHandler<VASurface> implementation.
scoped_refptr<VASurface> CreateSurface() override;
void SurfaceReady(const scoped_refptr<VASurface>& va_surface,
int32_t buffer_id,
const gfx::Rect& visible_rect,
const VideoColorSpace& color_space) override;
private:
// Decode task holding single decode request.
struct DecodeTask {
DecodeTask(scoped_refptr<DecoderBuffer> buffer,
int32_t buffer_id,
DecodeCB decode_done_cb);
~DecodeTask();
DecodeTask(DecodeTask&&);
DecodeTask& operator=(DecodeTask&&) = default;
scoped_refptr<DecoderBuffer> buffer_;
int32_t buffer_id_ = -1;
DecodeCB decode_done_cb_;
DISALLOW_COPY_AND_ASSIGN(DecodeTask);
};
enum class State {
kUninitialized, // not initialized yet or initialization failed.
kWaitingForInput, // waiting for input buffers.
kWaitingForOutput, // waiting for output buffers.
kDecoding, // decoding buffers.
kResetting, // resetting decoder.
kError, // decoder encountered an error.
};
VaapiVideoDecoder(scoped_refptr<base::SequencedTaskRunner> client_task_runner,
std::unique_ptr<DmabufVideoFramePool> frame_pool,
std::unique_ptr<VideoFrameConverter> frame_converter);
~VaapiVideoDecoder() override;
// Destroy the VAAPIVideoDecoder, aborts pending decode requests and blocks
// until destroyed.
void Destroy() override;
// Initialize the VAAPI video decoder on the decoder thread.
void InitializeTask(const VideoDecoderConfig& config,
InitCB init_cb,
OutputCB output_cb);
// Destroy the VAAPI video decoder on the decoder thread.
void DestroyTask();
// Queue a decode task on the decoder thread. If the decoder is currently
// waiting for input buffers decoding will be started.
void QueueDecodeTask(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb);
// Schedule the next decode task in the queue to be executed.
void ScheduleNextDecodeTask();
// Try to decode a single input buffer on the decoder thread.
void HandleDecodeTask();
// Clear the decode task queue on the decoder thread. This is done when
// resetting or destroying the decoder, or encountering an error.
void ClearDecodeTaskQueue(DecodeStatus status);
// Output a single |video_frame| on the decoder thread.
void OutputFrameTask(scoped_refptr<VideoFrame> video_frame);
// Called when a different output frame resolution is requested on the decoder
// thread. This happens when either decoding just started or a resolution
// change occurred in the video stream.
void ChangeFrameResolutionTask();
// Release the video frame associated with the specified |surface_id| on the
// decoder thread. This is called when the last reference to the associated
// VASurface has been released, which happens when the decoder outputted the
// video frame, or stopped using it as a reference frame. Note that this
// doesn't mean the frame can be reused immediately, as it might still be used
// by the client.
void ReleaseFrameTask(std::unique_ptr<VaapiPicture> picture,
VASurfaceID surface_id);
// Called when a video frame was returned to the video frame pool on the
// decoder thread. This will happen when both the client and decoder
// (in ReleaseFrameTask()) released their reference to the video frame.
void NotifyFrameAvailableTask();
// Flush the decoder on the decoder thread, blocks until all pending decode
// tasks have been executed and all frames have been output.
void FlushTask();
// Reset the decoder on the decoder thread. This will abort any pending decode
// task. The |reset_cb| will be passed to ResetDoneTask() and called when
// resetting has completed.
void ResetTask(base::OnceClosure reset_cb);
// Called on the decoder thread once resetting is done. Executes |reset_cb|.
void ResetDoneTask(base::OnceClosure reset_cb);
// Called on decoder thread to schedule |decode_cb| on the client task runner.
void RunDecodeCB(DecodeCB decode_cb, DecodeStatus status);
// Change the current |state_| to the specified |state| on the decoder thread.
void SetState(State state);
// The video decoder's state.
State state_ = State::kUninitialized;
// Callback used to notify the client when a frame is available for output.
OutputCB output_cb_;
// The video stream's profile.
VideoCodecProfile profile_ = VIDEO_CODEC_PROFILE_UNKNOWN;
// True if the decoder needs bitstream conversion before decoding.
bool needs_bitstream_conversion_ = false;
// Output frame properties.
gfx::Rect visible_rect_;
gfx::Size natural_size_;
// Video frame pool used to allocate and recycle video frames.
std::unique_ptr<DmabufVideoFramePool> frame_pool_;
// Video frame converter.
std::unique_ptr<VideoFrameConverter> frame_converter_;
// Queue containing all requested decode tasks.
base::queue<DecodeTask> decode_task_queue_;
// The decode task we're currently trying to execute.
base::Optional<DecodeTask> current_decode_task_;
// The next input buffer id.
int32_t next_buffer_id_ = 0;
// The list of frames currently used as output buffers or reference frames.
std::map<VASurfaceID, scoped_refptr<VideoFrame>> output_frames_;
// Platform and codec specific video decoder.
std::unique_ptr<AcceleratedVideoDecoder> decoder_;
scoped_refptr<VaapiWrapper> vaapi_wrapper_;
std::unique_ptr<VaapiPictureFactory> vaapi_picture_factory_;
const scoped_refptr<base::SequencedTaskRunner> client_task_runner_;
base::Thread decoder_thread_;
scoped_refptr<base::SingleThreadTaskRunner> decoder_thread_task_runner_;
SEQUENCE_CHECKER(client_sequence_checker_);
SEQUENCE_CHECKER(decoder_sequence_checker_);
base::WeakPtr<VaapiVideoDecoder> weak_this_;
base::WeakPtrFactory<VaapiVideoDecoder> weak_this_factory_;
DISALLOW_COPY_AND_ASSIGN(VaapiVideoDecoder);
};
} // namespace media
#endif // MEDIA_GPU_VAAPI_VAAPI_VIDEO_DECODER_H_
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