| // Copyright 2018 The Fuchsia 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 GARNET_DRIVERS_VIDEO_AMLOGIC_DECODER_VIDEO_DECODER_H_ |
| #define GARNET_DRIVERS_VIDEO_AMLOGIC_DECODER_VIDEO_DECODER_H_ |
| |
| #include <ddk/binding.h> |
| #include <ddk/debug.h> |
| #include <ddk/device.h> |
| #include <ddk/driver.h> |
| #include <fuchsia/mediacodec/cpp/fidl.h> |
| #include <lib/media/codec_impl/codec_frame.h> |
| #include <lib/zx/bti.h> |
| #include <zircon/assert.h> |
| #include <zircon/errors.h> |
| #include <zircon/syscalls.h> |
| |
| #include <functional> |
| |
| #include "decoder_core.h" |
| #include "pts_manager.h" |
| #include "registers.h" |
| #include "video_frame.h" |
| |
| class FirmwareBlob; |
| class PtsManager; |
| |
| enum class DeviceType { |
| kUnknown, |
| // These should be ordered from oldest to newest. |
| kGXM = 1, // S912 |
| kG12A = 2, // S905D2 |
| kG12B = 3, // T931 |
| }; |
| |
| // Returns true if |a| is newer than or the same as |b|. |
| inline bool IsDeviceAtLeast(DeviceType a, DeviceType b) { |
| return static_cast<int>(a) >= static_cast<int>(b); |
| } |
| |
| class CanvasEntry { |
| public: |
| class Owner { |
| public: |
| virtual void FreeCanvas(CanvasEntry* canvas) = 0; |
| }; |
| CanvasEntry(Owner* owner, uint32_t index) : owner_(owner), index_(index) {} |
| |
| ~CanvasEntry() { owner_->FreeCanvas(this); } |
| |
| __WARN_UNUSED_RESULT |
| uint32_t index() const { return index_; } |
| |
| private: |
| Owner* owner_; |
| uint32_t index_; |
| }; |
| |
| class CodecPacket; |
| class VideoDecoder { |
| public: |
| // In actual operation, the FrameReadyNotifier must not keep a reference on |
| // the frame shared_ptr<>, as that would interfere with muting calls to |
| // ReturnFrame(). See comment on Vp9Decoder::Frame::frame field. |
| using FrameReadyNotifier = std::function<void(std::shared_ptr<VideoFrame>)>; |
| using InitializeFramesHandler = |
| std::function<zx_status_t(::zx::bti, |
| uint32_t, // frame_count |
| uint32_t, // width |
| uint32_t, // height |
| uint32_t, // stride |
| uint32_t, // display_width |
| uint32_t, // display_height |
| bool, // has_sar |
| uint32_t, // sar_width |
| uint32_t // sar_height |
| )>; |
| using CheckOutputReady = fit::function<bool()>; |
| class Owner { |
| public: |
| virtual __WARN_UNUSED_RESULT DosRegisterIo* dosbus() = 0; |
| virtual __WARN_UNUSED_RESULT zx_handle_t bti() = 0; |
| virtual __WARN_UNUSED_RESULT DeviceType device_type() = 0; |
| virtual __WARN_UNUSED_RESULT FirmwareBlob* firmware_blob() = 0; |
| virtual __WARN_UNUSED_RESULT std::unique_ptr<CanvasEntry> ConfigureCanvas( |
| io_buffer_t* io_buffer, uint32_t offset, uint32_t width, |
| uint32_t height, uint32_t wrap, uint32_t blockmode) = 0; |
| virtual __WARN_UNUSED_RESULT DecoderCore* core() = 0; |
| virtual __WARN_UNUSED_RESULT zx_status_t |
| AllocateIoBuffer(io_buffer_t* buffer, size_t size, uint32_t alignement_log2, |
| uint32_t flags) = 0; |
| virtual __WARN_UNUSED_RESULT bool IsDecoderCurrent( |
| VideoDecoder* decoder) = 0; |
| }; |
| |
| VideoDecoder() { pts_manager_ = std::make_unique<PtsManager>(); } |
| |
| virtual __WARN_UNUSED_RESULT zx_status_t Initialize() = 0; |
| virtual __WARN_UNUSED_RESULT zx_status_t InitializeHardware() { |
| return ZX_ERR_NOT_SUPPORTED; |
| } |
| virtual void HandleInterrupt() = 0; |
| virtual void SetFrameReadyNotifier(FrameReadyNotifier notifier) = 0; |
| virtual void SetInitializeFramesHandler(InitializeFramesHandler handler) { |
| ZX_ASSERT_MSG(false, "not yet implemented"); |
| } |
| virtual void SetErrorHandler(fit::closure error_handler) { |
| ZX_ASSERT_MSG(false, "not yet implemented"); |
| } |
| virtual void SetCheckOutputReady(CheckOutputReady checkOutputReady) { |
| ZX_ASSERT_MSG(false, "not yet implemented"); |
| }; |
| virtual void ReturnFrame(std::shared_ptr<VideoFrame> frame) = 0; |
| virtual void InitializedFrames(std::vector<CodecFrame> frames, uint32_t width, |
| uint32_t height, uint32_t stride) = 0; |
| virtual void SetSwappedOut() {} |
| virtual void SwappedIn() {} |
| // Returns true if the instance has more data to decode and output buffers to |
| // decode it into. |
| virtual bool __WARN_UNUSED_RESULT CanBeSwappedIn() { return false; } |
| // Returns true if the decoder is at a place where it can be swapped out. |
| virtual bool __WARN_UNUSED_RESULT CanBeSwappedOut() const { return false; } |
| virtual ~VideoDecoder() {} |
| |
| __WARN_UNUSED_RESULT PtsManager* pts_manager() { return pts_manager_.get(); } |
| |
| protected: |
| std::unique_ptr<PtsManager> pts_manager_; |
| uint64_t next_non_codec_buffer_lifetime_ordinal_ = 0; |
| }; |
| |
| #endif // GARNET_DRIVERS_VIDEO_AMLOGIC_DECODER_VIDEO_DECODER_H_ |