blob: d1bdbb4d9c2602ecc65ad705ac0f4f9cc4fbf1e8 [file] [log] [blame]
// Copyright 2018 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_ENCODER_DELEGATE_H_
#define MEDIA_GPU_VAAPI_VAAPI_VIDEO_ENCODER_DELEGATE_H_
#include <va/va.h>
#include <vector>
#include "base/callback.h"
#include "base/containers/queue.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "media/base/video_bitrate_allocation.h"
#include "media/base/video_codecs.h"
#include "media/video/video_encode_accelerator.h"
#include "media/video/video_encoder_info.h"
#include "ui/gfx/geometry/size.h"
namespace base {
class RefCountedBytes;
}
namespace media {
struct BitstreamBufferMetadata;
class CodecPicture;
class ScopedVABuffer;
class VideoFrame;
class VASurface;
class VaapiWrapper;
// An VaapiVideoEncoderDelegate performs high-level, platform-independent
// encoding process tasks, such as managing codec state, reference frames, etc.,
// but may require support from an external accelerator (typically a hardware
// accelerator) to offload some stages of the actual encoding process, using
// the parameters that the Delegate prepares beforehand.
//
// For each frame to be encoded, clients provide an EncodeJob object to be set
// up by a Delegate subclass with job parameters, and execute the job
// afterwards. Any resources required for the job are also provided by the
// clients, and associated with the EncodeJob object.
class VaapiVideoEncoderDelegate {
public:
VaapiVideoEncoderDelegate(scoped_refptr<VaapiWrapper> vaapi_wrapper,
base::RepeatingClosure error_cb);
virtual ~VaapiVideoEncoderDelegate();
enum class BitrateControl {
kConstantBitrate, // Constant Bitrate mode. This class relies on other
// parts (e.g. driver) to achieve the specified bitrate.
kConstantQuantizationParameter // Constant Quantization Parameter mode.
// This class needs to compute a proper
// quantization parameter and give other
// parts (e.g. the driver) the value.
};
struct Config {
// Maxium number of reference frames.
// For H.264 encoding, the value represents the maximum number of reference
// frames for both the reference picture list 0 (bottom 16 bits) and the
// reference picture list 1 (top 16 bits).
size_t max_num_ref_frames;
BitrateControl bitrate_control = BitrateControl::kConstantBitrate;
};
// An abstraction of an encode job for one frame. Parameters required for an
// EncodeJob to be executed are prepared by an VaapiVideoEncoderDelegate,
// while the accelerator-specific callbacks required to set up and execute it
// are provided by the accelerator itself, based on these parameters.
// Accelerators are also responsible for providing any resources (such as
// memory for output and reference pictures, etc.) as needed.
class EncodeJob {
public:
// Creates an EncodeJob to encode |input_frame|, which will be executed
// by calling |execute_cb|. If |keyframe| is true, requests this job
// to produce a keyframe.
EncodeJob(scoped_refptr<VideoFrame> input_frame,
bool keyframe,
base::OnceClosure execute_cb);
// Constructor for VA-API.
EncodeJob(scoped_refptr<VideoFrame> input_frame,
bool keyframe,
base::OnceClosure execute_cb,
scoped_refptr<VASurface> input_surface,
scoped_refptr<CodecPicture> picture,
std::unique_ptr<ScopedVABuffer> coded_buffer);
EncodeJob(const EncodeJob&) = delete;
EncodeJob& operator=(const EncodeJob&) = delete;
~EncodeJob();
// Schedules a callback to be run immediately before this job is executed.
// Can be called multiple times to schedule multiple callbacks, and all
// of them will be run, in order added.
// Callbacks can be used to e.g. set up hardware parameters before the job
// is executed.
void AddSetupCallback(base::OnceClosure cb);
// Schedules a callback to be run immediately after this job is executed.
// Can be called multiple times to schedule multiple callbacks, and all
// of them will be run, in order added. Callbacks can be used to e.g. get
// the encoded buffer linear size.
void AddPostExecuteCallback(base::OnceClosure cb);
// Adds |ref_pic| to the list of pictures to be used as reference pictures
// for this frame, to ensure they remain valid until the job is executed
// (or discarded).
void AddReferencePicture(scoped_refptr<CodecPicture> ref_pic);
// Runs all setup callbacks previously scheduled, if any, in order added,
// and executes the job by calling the execute callback. Note that the
// actual job execution may be asynchronous, and returning from this method
// does not have to indicate that the job has been finished. The execute
// callback is responsible for retaining references to any resources that
// may be in use after this method returns however, so it is safe to release
// the EncodeJob object itself immediately after this method returns.
void Execute();
// Requests this job to produce a keyframe; requesting a keyframe may not
// always result in one being produced by the encoder (e.g. if it would
// not fit in the bitrate budget).
void ProduceKeyframe() { keyframe_ = true; }
// Returns true if this job has been requested to produce a keyframe.
bool IsKeyframeRequested() const { return keyframe_; }
// Returns the timestamp associated with this job.
base::TimeDelta timestamp() const { return timestamp_; }
// VA-API specific methods.
VABufferID coded_buffer_id() const;
const scoped_refptr<VASurface>& input_surface() const;
const scoped_refptr<CodecPicture>& picture() const;
private:
// Input VideoFrame to be encoded.
const scoped_refptr<VideoFrame> input_frame_;
// Source timestamp for |input_frame_|.
const base::TimeDelta timestamp_;
// True if this job is to produce a keyframe.
bool keyframe_;
// VA-API specific members.
// Input surface for video frame data or scaled data.
const scoped_refptr<VASurface> input_surface_;
const scoped_refptr<CodecPicture> picture_;
// Buffer that will contain the output bitstream data for this frame.
const std::unique_ptr<ScopedVABuffer> coded_buffer_;
// Callbacks to be run (in the same order as the order of AddSetupCallback()
// calls) to set up the job.
base::queue<base::OnceClosure> setup_callbacks_;
// Callbacks to be run (in the same order as the order of
// AddPostExecuteCallback() calls) to do post processing after execute.
base::queue<base::OnceClosure> post_execute_callbacks_;
// Callback to be run to execute this job.
base::OnceClosure execute_callback_;
// Reference pictures required for this job.
std::vector<scoped_refptr<CodecPicture>> reference_pictures_;
};
// Initializes the encoder with requested parameter set |config| and
// |ave_config|. Returns false if the requested set of parameters is not
// supported, true on success.
virtual bool Initialize(
const VideoEncodeAccelerator::Config& config,
const VaapiVideoEncoderDelegate::Config& ave_config) = 0;
// Updates current framerate and/or bitrate to |framerate| in FPS
// and the specified video bitrate allocation.
virtual bool UpdateRates(const VideoBitrateAllocation& bitrate_allocation,
uint32_t framerate) = 0;
// Returns coded size for the input buffers required to encode, in pixels;
// typically visible size adjusted to match codec alignment requirements.
virtual gfx::Size GetCodedSize() const = 0;
// Returns minimum size in bytes for bitstream buffers required to fit output
// stream buffers produced.
virtual size_t GetBitstreamBufferSize() const;
// Returns maximum number of reference frames that may be used by the
// encoder to encode one frame. The client should be able to provide up to
// at least this many frames simultaneously for encode to make progress.
virtual size_t GetMaxNumOfRefFrames() const = 0;
// Prepares a new |encode_job| to be executed in Accelerator and returns true
// on success. The caller may then call Execute() on the job to run it.
virtual bool PrepareEncodeJob(EncodeJob* encode_job) = 0;
// Notifies the encoded chunk size in bytes to update a bitrate controller in
// VaapiVideoEncoderDelegate. This should be called only if
// VaapiVideoEncoderDelegate is configured with
// BitrateControl::kConstantQuantizationParameter.
virtual void BitrateControlUpdate(uint64_t encoded_chunk_size_bytes);
virtual BitstreamBufferMetadata GetMetadata(EncodeJob* encode_job,
size_t payload_size);
// Gets the active spatial layer resolutions for K-SVC encoding, VaapiVEA
// can get this info from the encoder delegate. Returns empty vector on
// failure.
virtual std::vector<gfx::Size> GetSVCLayerResolutions() = 0;
// Submits |buffer| of |type| to the driver.
void SubmitBuffer(VABufferType type,
scoped_refptr<base::RefCountedBytes> buffer);
// Submits a VAEncMiscParameterBuffer |buffer| of type |type| to the driver.
void SubmitVAEncMiscParamBuffer(VAEncMiscParameterType type,
scoped_refptr<base::RefCountedBytes> buffer);
protected:
const scoped_refptr<VaapiWrapper> vaapi_wrapper_;
base::RepeatingClosure error_cb_;
SEQUENCE_CHECKER(sequence_checker_);
};
} // namespace media
#endif // MEDIA_GPU_VAAPI_VAAPI_VIDEO_ENCODER_DELEGATE_H_