123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- // Copyright 2014 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_ENCODE_ACCELERATOR_H_
- #define MEDIA_GPU_VAAPI_VAAPI_VIDEO_ENCODE_ACCELERATOR_H_
- #include <stddef.h>
- #include <stdint.h>
- #include <map>
- #include <memory>
- #include "base/containers/queue.h"
- #include "base/containers/small_map.h"
- #include "base/memory/ref_counted_memory.h"
- #include "base/sequence_checker.h"
- #include "base/task/single_thread_task_runner.h"
- #include "base/trace_event/memory_dump_provider.h"
- #include "media/base/bitrate.h"
- #include "media/gpu/media_gpu_export.h"
- #include "media/gpu/vaapi/vaapi_utils.h"
- #include "media/gpu/vaapi/vaapi_video_encoder_delegate.h"
- #include "media/gpu/vaapi/vaapi_wrapper.h"
- #include "media/video/video_encode_accelerator.h"
- namespace media {
- // A VideoEncodeAccelerator implementation that uses VA-API
- // (https://01.org/vaapi) for HW-accelerated video encode.
- class MEDIA_GPU_EXPORT VaapiVideoEncodeAccelerator
- : public VideoEncodeAccelerator,
- public base::trace_event::MemoryDumpProvider {
- public:
- VaapiVideoEncodeAccelerator();
- VaapiVideoEncodeAccelerator(const VaapiVideoEncodeAccelerator&) = delete;
- VaapiVideoEncodeAccelerator& operator=(const VaapiVideoEncodeAccelerator&) =
- delete;
- ~VaapiVideoEncodeAccelerator() override;
- // VideoEncodeAccelerator implementation.
- SupportedProfiles GetSupportedProfiles() override;
- bool Initialize(const Config& config,
- Client* client,
- std::unique_ptr<MediaLog> media_log) override;
- void Encode(scoped_refptr<VideoFrame> frame, bool force_keyframe) override;
- void UseOutputBitstreamBuffer(BitstreamBuffer buffer) override;
- void RequestEncodingParametersChange(const Bitrate& bitrate,
- uint32_t framerate) override;
- void RequestEncodingParametersChange(
- const VideoBitrateAllocation& bitrate_allocation,
- uint32_t framerate) override;
- void Destroy() override;
- void Flush(FlushCallback flush_callback) override;
- bool IsFlushSupported() override;
- // base::trace_event::MemoryDumpProvider implementation.
- bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
- base::trace_event::ProcessMemoryDump* pmd) override;
- private:
- friend class VaapiVideoEncodeAcceleratorTest;
- using EncodeJob = VaapiVideoEncoderDelegate::EncodeJob;
- using EncodeResult = VaapiVideoEncoderDelegate::EncodeResult;
- // Encoder state.
- enum State {
- kUninitialized,
- kEncoding,
- kError,
- };
- struct SizeComparator {
- constexpr bool operator()(const gfx::Size& lhs,
- const gfx::Size& rhs) const {
- return std::forward_as_tuple(lhs.width(), lhs.height()) <
- std::forward_as_tuple(rhs.width(), rhs.height());
- }
- };
- // Maximum size is four to support the worst case of a given input of a
- // different resolution than the maximum number of spatial layers (3).
- static constexpr size_t kMaxNumSpatialLayersPlusOne = 3 + 1;
- using InputSurfaceMap = base::small_map<
- std::map<gfx::Size, std::unique_ptr<ScopedVASurface>, SizeComparator>,
- kMaxNumSpatialLayersPlusOne>;
- using EncodeSurfacesMap =
- base::small_map<std::map<gfx::Size,
- std::vector<std::unique_ptr<ScopedVASurface>>,
- SizeComparator>,
- kMaxNumSpatialLayersPlusOne>;
- using EncodeSurfacesCountMap =
- base::small_map<std::map<gfx::Size, size_t, SizeComparator>,
- kMaxNumSpatialLayersPlusOne>;
- // Holds input frames coming from the client ready to be encoded.
- struct InputFrameRef;
- // Holds output buffers coming from the client ready to be filled.
- struct BitstreamBufferRef;
- //
- // Tasks for each of the VEA interface calls to be executed on
- // |encoder_task_runner_|.
- //
- void InitializeTask(const Config& config);
- bool AttemptedInitialization() const { return !!client_ptr_factory_; }
- // Enqueues |frame| onto the queue of pending inputs and attempts to continue
- // encoding.
- void EncodeTask(scoped_refptr<VideoFrame> frame, bool force_keyframe);
- // Maps |buffer_ref|, push it onto the available_bitstream_buffers_, and
- // attempts to return any pending encoded data in it, if any.
- void UseOutputBitstreamBufferTask(
- std::unique_ptr<BitstreamBufferRef> buffer_ref);
- void RequestEncodingParametersChangeTask(
- VideoBitrateAllocation bitrate_allocation,
- uint32_t framerate);
- void DestroyTask();
- void FlushTask(FlushCallback flush_callback);
- // Create input and reconstructed surfaces used in encoding whose sizes are
- // |spatial_layer_resolutions| from GpuMemoryBuffer-based VideoFrame |frame|.
- // The created surfaces for input to an encoder driver are filled into
- // |input_surfaces| and, ones used as reconstructed surfaces by the driver are
- // filled to |reconstructed_surfaces|. This must be called only in native
- // input mode.
- bool CreateSurfacesForGpuMemoryBufferEncoding(
- const VideoFrame& frame,
- const std::vector<gfx::Size>& spatial_layer_resolutions,
- std::vector<scoped_refptr<VASurface>>* input_surfaces,
- std::vector<scoped_refptr<VASurface>>* reconstructed_surfaces);
- // Create input and reconstructed surfaces used in encoding from SharedMemory
- // VideoFrame |frame|. This must be called only in non native input mode.
- bool CreateSurfacesForShmemEncoding(
- const VideoFrame& frame,
- scoped_refptr<VASurface>* input_surface,
- scoped_refptr<VASurface>* reconstructed_surface);
- // Creates one |encode_size| VASurface using |vaapi_wrapper_|.
- // It returns a reference of an exiting available surface. If there is no
- // available surface and the number of previously allocated surfaces is less
- // than threshold, then it returns a reference to the newly created
- // surface, that is also added to |available_encode_surfaces_[encode_size]|.
- // Returns nullptr if too many surfaces have already been allocated, or if
- // creation fails.
- scoped_refptr<VASurface> CreateEncodeSurface(const gfx::Size& encode_size);
- // Creates VASurface using |vaapi_wrapper| whose sizes are |encode_size|
- // with |surface_usage_hints|. Returns nullptr if the surfaces fail to be
- // created successfully. The created surfaces are filled into
- // |input_surfaces_[encode_size]|.
- scoped_refptr<VASurface> CreateInputSurface(
- VaapiWrapper& vaapi_wrapper,
- const gfx::Size& encode_size,
- const std::vector<VaapiWrapper::SurfaceUsageHint>& surface_usage_hints);
- // Creates |vpp_vaapi_wrapper_| if it hasn't been created.
- scoped_refptr<VaapiWrapper> CreateVppVaapiWrapper();
- // Executes BlitSurface() using |vpp_vaapi_wrapper_| with |source_surface|,
- // |source_visible_rect|. Returns the destination VASurface in BlitSurface()
- // whose size is |encode_size| on success, otherwise nullptr.
- scoped_refptr<VASurface> ExecuteBlitSurface(
- const VASurface& source_surface,
- const gfx::Rect source_visible_rect,
- const gfx::Size& encode_size);
- // Checks if sufficient resources for a new encode job with |frame| as input
- // are available, and if so, claims them by associating them with
- // a EncodeJob, and returns the newly-created job, nullptr otherwise.
- std::unique_ptr<EncodeJob> CreateEncodeJob(
- bool force_keyframe,
- base::TimeDelta frame_timestamp,
- const VASurface& input_surface,
- scoped_refptr<VASurface> reconstructed_surface);
- // Continues encoding frames as long as input_queue_ is not empty, and we are
- // able to create new EncodeJobs.
- void EncodePendingInputs();
- // Callback that returns a no longer used ScopedVASurface to
- // |va_surfaces| for reuse and kicks EncodePendingInputs() again.
- void RecycleVASurface(
- std::vector<std::unique_ptr<ScopedVASurface>>* va_surfaces,
- std::unique_ptr<ScopedVASurface> va_surface,
- VASurfaceID va_surface_id);
- // Returns pending bitstream buffers to the client if we have both pending
- // encoded data to be completed and bitstream buffers available to download
- // the encoded data into.
- void TryToReturnBitstreamBuffers();
- // Downloads encoded data produced as a result of running |encode_result| into
- // |buffer|, and returns it to the client.
- void ReturnBitstreamBuffer(std::unique_ptr<EncodeResult> encode_result,
- std::unique_ptr<BitstreamBufferRef> buffer);
- // Puts the encoder into en error state and notifies the client
- // about the error.
- void NotifyError(Error error);
- // Sets the encoder state to |state| on the correct thread.
- void SetState(State state);
- bool IsConfiguredForTesting() const {
- return !supported_profiles_for_testing_.empty();
- }
- // Having too many encoder instances at once may cause us to run out of FDs
- // and subsequently crash (crbug.com/1289465). To avoid that, we limit the
- // maximum number of encoder instances that can exist at once.
- // |num_instances_| tracks that number.
- static constexpr int kMaxNumOfInstances = 10;
- static base::AtomicRefCount num_instances_;
- const bool can_use_encoder_;
- // The unchanged values are filled upon the construction. The varied values
- // are filled properly during encoding.
- VideoEncoderInfo encoder_info_;
- // VaapiWrapper is the owner of all HW resources (surfaces and buffers)
- // and will free them on destruction.
- scoped_refptr<VaapiWrapper> vaapi_wrapper_
- GUARDED_BY_CONTEXT(encoder_sequence_checker_);
- // The expected coded size of incoming video frames when |native_input_mode_|
- // is false.
- gfx::Size expected_input_coded_size_;
- // The codec of the stream to be produced. Set during initialization.
- VideoCodec output_codec_ = VideoCodec::kUnknown;
- // The visible rect to be encoded.
- gfx::Rect visible_rect_;
- // Size in bytes required for output bitstream buffers.
- size_t output_buffer_byte_size_;
- // This flag signals when the client is sending NV12 + DmaBuf-backed
- // VideoFrames to encode, which allows for skipping a copy-adaptation on
- // input.
- bool native_input_mode_ = false;
- // The number of frames that needs to be held on encoding.
- size_t num_frames_in_flight_;
- // All of the members below must be accessed on the encoder_task_runner_,
- // while it is running.
- // Encoder state. Encode tasks will only run in kEncoding state.
- State state_;
- // Encoder instance managing video codec state and preparing encode jobs.
- // Should only be used on |encoder_task_runner_|.
- std::unique_ptr<VaapiVideoEncoderDelegate> encoder_;
- // Map of input surfaces. In non |native_input_mode_|, this is always created
- // and memory-based encode input VideoFrame is written into this.
- // In |native_input_mode_|, this is created only if scaling or cropping is
- // required and used as a VPP destination.
- InputSurfaceMap input_surfaces_;
- // Map of available reconstructed surfaces for encoding index by a layer
- // resolution. These are stored as reference frames in
- // VaapiVideoEncoderDelegate if necessary.
- EncodeSurfacesMap available_encode_surfaces_;
- // Map of the number of allocated reconstructed surfaces for encoding
- // indexed by a layer resolution.
- EncodeSurfacesCountMap encode_surfaces_count_;
- // Queue of input frames to be encoded.
- base::queue<std::unique_ptr<InputFrameRef>> input_queue_;
- // BitstreamBuffers mapped, ready to be filled with encoded stream data.
- base::queue<std::unique_ptr<BitstreamBufferRef>> available_bitstream_buffers_;
- // VASurfaces already encoded and waiting for the bitstream buffer to
- // be downloaded.
- base::queue<std::unique_ptr<EncodeResult>> pending_encode_results_;
- // Task runner for interacting with the client, and its checker.
- const scoped_refptr<base::SingleThreadTaskRunner> child_task_runner_;
- SEQUENCE_CHECKER(child_sequence_checker_);
- // Encoder sequence and its checker. All tasks are executed on it.
- const scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner_;
- SEQUENCE_CHECKER(encoder_sequence_checker_);
- // To expose client callbacks from VideoEncodeAccelerator.
- // NOTE: all calls to these objects *MUST* be executed on
- // child_task_runner_.
- std::unique_ptr<base::WeakPtrFactory<Client>> client_ptr_factory_;
- base::WeakPtr<Client> client_;
- // VaapiWrapper for VPP (Video Pre Processing). This is used for scale down
- // for the picture send to vaapi encoder.
- scoped_refptr<VaapiWrapper> vpp_vaapi_wrapper_
- GUARDED_BY_CONTEXT(encoder_sequence_checker_);
- // The completion callback of the Flush() function.
- FlushCallback flush_callback_;
- // Supported profiles that are filled if and only if in a unit test.
- SupportedProfiles supported_profiles_for_testing_;
- // WeakPtr of this, bound to |child_task_runner_|.
- base::WeakPtr<VaapiVideoEncodeAccelerator> child_weak_this_;
- // WeakPtr of this, bound to |encoder_task_runner_|.
- base::WeakPtr<VaapiVideoEncodeAccelerator> encoder_weak_this_;
- base::WeakPtrFactory<VaapiVideoEncodeAccelerator> child_weak_this_factory_{
- this};
- base::WeakPtrFactory<VaapiVideoEncodeAccelerator> encoder_weak_this_factory_{
- this};
- };
- } // namespace media
- #endif // MEDIA_GPU_VAAPI_VAAPI_VIDEO_ENCODE_ACCELERATOR_H_
|