blob: 47648a8f9010ae40c5828e83f9654f629374bf0e [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.
#ifndef MEDIA_VIDEO_VIDEO_ENCODE_ACCELERATOR_ADAPTER_H_
#define MEDIA_VIDEO_VIDEO_ENCODE_ACCELERATOR_ADAPTER_H_
#include <memory>
#include "base/callback_forward.h"
#include "base/containers/circular_deque.h"
#include "base/containers/queue.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/unsafe_shared_memory_pool.h"
#include "base/synchronization/lock.h"
#include "media/base/media_export.h"
#include "media/base/video_encoder.h"
#include "media/video/video_encode_accelerator.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/size.h"
namespace base {
class SequencedTaskRunner;
}
namespace media {
class GpuVideoAcceleratorFactories;
class H264AnnexBToAvcBitstreamConverter;
// This class is a somewhat complex adapter from VideoEncodeAccelerator
// to VideoEncoder, it takes cares of such things as
// - managing and copying GPU/shared memory buffers
// - managing hops between task runners, for VEA and callbacks
// - keeping track of the state machine. Forbiding encodes during flush etc.
class MEDIA_EXPORT VideoEncodeAcceleratorAdapter
: public VideoEncoder,
public VideoEncodeAccelerator::Client {
public:
VideoEncodeAcceleratorAdapter(
GpuVideoAcceleratorFactories* gpu_factories,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner);
~VideoEncodeAcceleratorAdapter() override;
enum class InputBufferKind { Any, GpuMemBuf, CpuMemBuf };
// A way to force a certain way of submitting frames to VEA.
void SetInputBufferPreferenceForTesting(InputBufferKind type);
// VideoEncoder implementation.
void Initialize(VideoCodecProfile profile,
const Options& options,
OutputCB output_cb,
StatusCB done_cb) override;
void Encode(scoped_refptr<VideoFrame> frame,
bool key_frame,
StatusCB done_cb) override;
void ChangeOptions(const Options& options,
OutputCB output_cb,
StatusCB done_cb) override;
void Flush(StatusCB done_cb) override;
// VideoEncodeAccelerator::Client implementation
void RequireBitstreamBuffers(unsigned int input_count,
const gfx::Size& input_coded_size,
size_t output_buffer_size) override;
void BitstreamBufferReady(int32_t buffer_id,
const BitstreamBufferMetadata& metadata) override;
void NotifyError(VideoEncodeAccelerator::Error error) override;
void NotifyEncoderInfoChange(const VideoEncoderInfo& info) override;
// For async disposal by AsyncDestroyVideoEncoder
static void DestroyAsync(std::unique_ptr<VideoEncodeAcceleratorAdapter> self);
private:
enum class State {
kNotInitialized,
kWaitingForFirstFrame,
kInitializing,
kReadyToEncode,
kFlushing
};
struct PendingOp {
PendingOp();
~PendingOp();
StatusCB done_callback;
base::TimeDelta timestamp;
};
void FlushCompleted(bool success);
void InitCompleted(Status status);
void InitializeOnAcceleratorThread(VideoCodecProfile profile,
const Options& options,
OutputCB output_cb,
StatusCB done_cb);
void InitializeInternalOnAcceleratorThread();
void EncodeOnAcceleratorThread(scoped_refptr<VideoFrame> frame,
bool key_frame,
StatusCB done_cb);
void FlushOnAcceleratorThread(StatusCB done_cb);
void ChangeOptionsOnAcceleratorThread(const Options options,
OutputCB output_cb,
StatusCB done_cb);
template <class T>
T WrapCallback(T cb);
StatusOr<scoped_refptr<VideoFrame>> PrepareGpuFrame(
const gfx::Size& size,
scoped_refptr<VideoFrame> src_frame);
StatusOr<scoped_refptr<VideoFrame>> PrepareCpuFrame(
const gfx::Size& size,
scoped_refptr<VideoFrame> src_frame);
scoped_refptr<base::UnsafeSharedMemoryPool> output_pool_;
scoped_refptr<base::UnsafeSharedMemoryPool> input_pool_;
std::unique_ptr<base::UnsafeSharedMemoryPool::Handle> output_handle_holder_;
size_t input_buffer_size_;
std::unique_ptr<VideoEncodeAccelerator> accelerator_;
GpuVideoAcceleratorFactories* gpu_factories_;
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
// If |h264_converter_| is null, we output in annexb format. Otherwise, we
// output in avc format.
std::unique_ptr<H264AnnexBToAvcBitstreamConverter> h264_converter_;
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
// These are encodes that have been sent to the accelerator but have not yet
// had their encoded data returned via BitstreamBufferReady().
base::circular_deque<std::unique_ptr<PendingOp>> active_encodes_;
std::unique_ptr<PendingOp> pending_flush_;
// For calling accelerator_ methods
scoped_refptr<base::SequencedTaskRunner> accelerator_task_runner_;
SEQUENCE_CHECKER(accelerator_sequence_checker_);
// For calling user provided callbacks
scoped_refptr<base::SequencedTaskRunner> callback_task_runner_;
State state_ = State::kNotInitialized;
absl::optional<bool> flush_support_;
// True if underlying instance of VEA can handle GPU backed frames with a
// size different from what VEA was configured for.
bool gpu_resize_supported_ = false;
// These are encodes that have not been sent to the accelerator.
std::vector<std::unique_ptr<PendingEncode>> pending_encodes_;
VideoPixelFormat format_;
InputBufferKind input_buffer_preference_ = InputBufferKind::Any;
std::vector<uint8_t> resize_buf_;
VideoCodecProfile profile_ = VIDEO_CODEC_PROFILE_UNKNOWN;
Options options_;
OutputCB output_cb_;
gfx::Size input_coded_size_;
};
} // namespace media
#endif // MEDIA_VIDEO_VIDEO_ENCODE_ACCELERATOR_ADAPTER_H_