blob: 6da313573c188bb8f96bb7da1ca624d7414a1bdd [file] [log] [blame]
// Copyright 2020 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.
#include <array>
#include <memory>
#include "base/containers/span.h"
#include "base/macros.h"
#include "base/sequence_checker.h"
#include "media/base/video_codecs.h"
#include "media/base/video_color_space.h"
#include "media/gpu/accelerated_video_decoder.h"
#include "media/gpu/media_gpu_export.h"
#include "third_party/libgav1/src/src/utils/constants.h"
// For libgav1::RefCountedBufferPtr.
#include "third_party/libgav1/src/src/buffer_pool.h"
// For libgav1::ObuSequenceHeader. absl::optional demands ObuSequenceHeader to
// fulfill std::is_trivially_constructible if it is forward-declared. But
// ObuSequenceHeader doesn't.
#include "third_party/libgav1/src/src/obu_parser.h"
namespace libgav1 {
struct DecoderState;
struct ObuFrameHeader;
template <typename T>
class Vector;
} // namespace libgav1
namespace media {
class AV1Picture;
using AV1ReferenceFrameVector =
std::array<scoped_refptr<AV1Picture>, libgav1::kNumReferenceFrameTypes>;
// Clients of this class are expected to pass an AV1 OBU stream and are expected
// to provide an implementation of AV1Accelerator for offloading final steps
// of the decoding process.
// This class must be created, called and destroyed on a single thread, and
// does nothing internally on any other thread.
class MEDIA_GPU_EXPORT AV1Decoder : public AcceleratedVideoDecoder {
class MEDIA_GPU_EXPORT AV1Accelerator {
// Methods may return kTryAgain if they need additional data (provided
// independently) in order to proceed. Examples are things like not having
// an appropriate key to decode encrypted content. This is not considered an
// unrecoverable error, but rather a pause to allow an application to
// independently provide the required data. When AV1Decoder::Decode()
// is called again, it will attempt to resume processing of the stream
// by calling the same method again.
enum class Status {
// Operation completed successfully.
// Operation failed.
// Operation failed because some external data is missing. Retry the same
// operation later, once the data has been provided.
AV1Accelerator() = default;
virtual ~AV1Accelerator() = default;
AV1Accelerator(const AV1Accelerator&) = delete;
AV1Accelerator& operator=(const AV1Accelerator&) = delete;
// Creates an AV1Picture that the AV1Decoder can use to store some of the
// information needed to request accelerated decoding. This picture is later
// passed when calling SubmitDecode() so that the AV1Accelerator can submit
// the decode request to the driver. It may also be stored for use as
// reference to decode other pictures.
// When a picture is no longer needed by the decoder, it will just drop
// its reference to it, and it may do so at any time.
// Note that this may return nullptr if the accelerator is not able to
// provide any new pictures at the given time. The decoder must handle this
// case and treat it as normal, returning kRanOutOfSurfaces from Decode().
virtual scoped_refptr<AV1Picture> CreateAV1Picture(bool apply_grain) = 0;
// Submits |pic| to the driver for accelerated decoding. The following
// parameters are also passed:
// - |sequence_header|: the current OBU sequence header.
// - |ref_frames|: the pictures used as reference for decoding |pic|.
// - |tile_buffers|: tile information.
// - |data|: the entire data of the DecoderBuffer set by
// AV1Decoder::SetStream().
// Note that returning from this method does not mean that the decode
// process is finished, but the caller may drop its references to |pic|
// and |ref_frames| immediately, and |data| does not need to remain valid
// after this method returns.
virtual Status SubmitDecode(
const AV1Picture& pic,
const libgav1::ObuSequenceHeader& sequence_header,
const AV1ReferenceFrameVector& ref_frames,
const libgav1::Vector<libgav1::TileBuffer>& tile_buffers,
base::span<const uint8_t> data) = 0;
// Schedules output (display) of |pic|.
// Note that returning from this method does not mean that |pic| has already
// been outputted (displayed), but guarantees that all pictures will be
// outputted in the same order as this method was called for them, and that
// they are decoded before outputting (assuming SubmitDecode() has been
// called for them beforehand).
// Returns true when successful, false otherwise.
virtual bool OutputPicture(const AV1Picture& pic) = 0;
AV1Decoder(std::unique_ptr<AV1Accelerator> accelerator,
VideoCodecProfile profile,
const VideoColorSpace& container_color_space = VideoColorSpace());
~AV1Decoder() override;
AV1Decoder(const AV1Decoder&) = delete;
AV1Decoder& operator=(const AV1Decoder&) = delete;
// AcceleratedVideoDecoder implementation.
void SetStream(int32_t id, const DecoderBuffer& decoder_buffer) override;
bool Flush() override WARN_UNUSED_RESULT;
void Reset() override;
DecodeResult Decode() override WARN_UNUSED_RESULT;
gfx::Size GetPicSize() const override;
gfx::Rect GetVisibleRect() const override;
VideoCodecProfile GetProfile() const override;
uint8_t GetBitDepth() const override;
size_t GetRequiredNumOfPictures() const override;
size_t GetNumReferenceFrames() const override;
friend class AV1DecoderTest;
AV1Accelerator::Status DecodeAndOutputPicture(
scoped_refptr<AV1Picture> pic,
const libgav1::Vector<libgav1::TileBuffer>& tile_buffers);
void UpdateReferenceFrames(scoped_refptr<AV1Picture> pic);
void ClearReferenceFrames();
// Checks that |ref_frames_| is consistent with libgav1's reference frame
// state (returns false if not) and cleans old reference frames from
// |ref_frames_| as needed. Also asserts that all reference frames needed by
// |current_frame_header_| are in |ref_frames_|. This method should be called
// prior to using |ref_frames_| (which includes calling
// |accelerator_|->SubmitDecode());
bool CheckAndCleanUpReferenceFrames();
void ClearCurrentFrame();
DecodeResult DecodeInternal();
bool on_error_ = false;
std::unique_ptr<libgav1::BufferPool> buffer_pool_;
std::unique_ptr<libgav1::DecoderState> state_;
std::unique_ptr<libgav1::ObuParser> parser_;
const std::unique_ptr<AV1Accelerator> accelerator_;
AV1ReferenceFrameVector ref_frames_;
absl::optional<libgav1::ObuSequenceHeader> current_sequence_header_;
absl::optional<libgav1::ObuFrameHeader> current_frame_header_;
libgav1::RefCountedBufferPtr current_frame_;
gfx::Rect visible_rect_;
gfx::Size frame_size_;
VideoCodecProfile profile_;
VideoColorSpace container_color_space_;
uint8_t bit_depth_ = 0;
int32_t stream_id_ = 0;
const uint8_t* stream_ = nullptr;
size_t stream_size_ = 0;
std::unique_ptr<DecryptConfig> decrypt_config_;
// Pending picture for decode when accelerator returns kTryAgain.
scoped_refptr<AV1Picture> pending_pic_;
} // namespace media