| // Copyright (c) 2012 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_DECODE_ACCELERATOR_H_ |
| #define MEDIA_VIDEO_VIDEO_DECODE_ACCELERATOR_H_ |
| |
| #include <stdint.h> |
| |
| #include <memory> |
| #include <vector> |
| |
| #include "base/memory/scoped_refptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/unguessable_token.h" |
| #include "media/base/bitstream_buffer.h" |
| #include "media/base/cdm_context.h" |
| #include "media/base/decoder_buffer.h" |
| #include "media/base/encryption_scheme.h" |
| #include "media/base/overlay_info.h" |
| #include "media/base/status.h" |
| #include "media/base/video_decoder_config.h" |
| #include "media/video/picture.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| #include "ui/gfx/color_space.h" |
| #include "ui/gfx/geometry/size.h" |
| #include "ui/gfx/gpu_memory_buffer.h" |
| |
| typedef unsigned int GLenum; |
| |
| namespace base { |
| class SingleThreadTaskRunner; |
| } |
| |
| namespace gpu { |
| class SharedImageStub; |
| } |
| |
| namespace media { |
| |
| class CommandBufferHelper; |
| |
| // Video decoder interface. |
| // This interface is extended by the various components that ultimately |
| // implement the backend of PPB_VideoDecoder_Dev. |
| class MEDIA_EXPORT VideoDecodeAccelerator { |
| public: |
| // Specification of a decoding profile supported by a decoder. |
| // |max_resolution| and |min_resolution| are inclusive. |
| struct MEDIA_EXPORT SupportedProfile { |
| SupportedProfile(); |
| ~SupportedProfile(); |
| VideoCodecProfile profile; |
| gfx::Size max_resolution; |
| gfx::Size min_resolution; |
| bool encrypted_only; |
| }; |
| using SupportedProfiles = std::vector<SupportedProfile>; |
| |
| struct MEDIA_EXPORT Capabilities { |
| Capabilities(); |
| Capabilities(const Capabilities& other); |
| ~Capabilities(); |
| |
| std::string AsHumanReadableString() const; |
| |
| // Flags that can be associated with a VDA. |
| enum Flags { |
| NO_FLAGS = 0, |
| |
| // Normally, the VDA is required to be able to provide all PictureBuffers |
| // to the client via PictureReady(), even if the client does not return |
| // any of them via ReusePictureBuffer(). The client is only required to |
| // return PictureBuffers when it holds all of them, if it wants to get |
| // more decoded output. See VideoDecoder::CanReadWithoutStalling for |
| // more context. |
| // If this flag is set, then the VDA does not make this guarantee. The |
| // client must return PictureBuffers to be sure that new frames will be |
| // provided via PictureReady. |
| NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE = 1 << 0, |
| |
| // Whether the VDA supports being configured with an output surface for |
| // it to render frames to. For example, SurfaceViews on Android. |
| SUPPORTS_EXTERNAL_OUTPUT_SURFACE = 1 << 1, |
| |
| // If set, the VDA will use deferred initialization if the config |
| // indicates that the client supports it as well. Refer to |
| // NotifyInitializationComplete for more details. |
| SUPPORTS_DEFERRED_INITIALIZATION = 1 << 2, |
| |
| // If set, video frames will have COPY_REQUIRED flag which will cause |
| // an extra texture copy during composition. |
| REQUIRES_TEXTURE_COPY = 1 << 3, |
| |
| // Whether the VDA supports encrypted streams or not. |
| SUPPORTS_ENCRYPTED_STREAMS = 1 << 4, |
| |
| // If set the decoder does not require a restart in order to switch to |
| // using an external output surface. |
| SUPPORTS_SET_EXTERNAL_OUTPUT_SURFACE = 1 << 5, |
| }; |
| |
| SupportedProfiles supported_profiles; |
| uint32_t flags; |
| }; |
| |
| // Enumeration of potential errors generated by the API. |
| // Note: Keep these in sync with PP_VideoDecodeError_Dev. Also do not |
| // rearrange, reuse or remove values as they are used for gathering UMA |
| // statistics. |
| enum Error { |
| // An operation was attempted during an incompatible decoder state. |
| ILLEGAL_STATE = 1, |
| // Invalid argument was passed to an API method. |
| INVALID_ARGUMENT, |
| // Encoded input is unreadable. |
| UNREADABLE_INPUT, |
| // A failure occurred at the browser layer or one of its dependencies. |
| // Examples of such failures include GPU hardware failures, GPU driver |
| // failures, GPU library failures, browser programming errors, and so on. |
| PLATFORM_FAILURE, |
| // Largest used enum. This should be adjusted when new errors are added. |
| ERROR_MAX = PLATFORM_FAILURE, |
| }; |
| |
| // Config structure contains parameters required for the VDA initialization. |
| struct MEDIA_EXPORT Config { |
| // Specifies the allocation and handling mode for output PictureBuffers. |
| // When set to ALLOCATE, the VDA is expected to allocate backing memory |
| // for PictureBuffers at the time of AssignPictureBuffers() call. |
| // When set to IMPORT, the VDA will not allocate, but after receiving |
| // AssignPictureBuffers() call, it will expect a call to |
| // ImportBufferForPicture() for each PictureBuffer before use. |
| enum class OutputMode { |
| ALLOCATE, |
| IMPORT, |
| }; |
| |
| Config(); |
| Config(const Config& config); |
| |
| explicit Config(VideoCodecProfile profile); |
| |
| ~Config(); |
| |
| std::string AsHumanReadableString() const; |
| bool is_encrypted() const { |
| return encryption_scheme != EncryptionScheme::kUnencrypted; |
| } |
| |
| // The video codec and profile. |
| VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; |
| |
| // Whether the stream is encrypted, and, if so, the scheme used. |
| EncryptionScheme encryption_scheme = EncryptionScheme::kUnencrypted; |
| |
| // The CDM that the VDA should use to decode encrypted streams. Must be |
| // set to a valid ID if |is_encrypted|. |
| absl::optional<base::UnguessableToken> cdm_id; |
| |
| // Whether the client supports deferred initialization. |
| bool is_deferred_initialization_allowed = false; |
| |
| // Optional overlay info available at startup, rather than waiting for the |
| // VDA to receive a callback. |
| OverlayInfo overlay_info; |
| |
| // Coded size of the video frame hint, subject to change. |
| gfx::Size initial_expected_coded_size = gfx::Size(320, 240); |
| |
| OutputMode output_mode = OutputMode::ALLOCATE; |
| |
| // The list of picture buffer formats that the client knows how to use. An |
| // empty list means any format is supported. |
| std::vector<VideoPixelFormat> supported_output_formats; |
| |
| // The H264 SPS and PPS configuration data. Not all clients populate these |
| // fields, so they should be parsed from the bitstream instead, if required. |
| // Each SPS and PPS is prefixed with the Annex B framing bytes: 0, 0, 0, 1. |
| std::vector<uint8_t> sps; |
| std::vector<uint8_t> pps; |
| |
| // Color space specified by the container. |
| VideoColorSpace container_color_space; |
| |
| // Target color space. |
| // Used as a hint to the decoder. Outputting VideoFrames in this color space |
| // may avoid extra conversion steps. |
| gfx::ColorSpace target_color_space; |
| |
| // HDR metadata specified by the container. |
| absl::optional<gfx::HDRMetadata> hdr_metadata; |
| }; |
| |
| // Interface for collaborating with picture interface to provide memory for |
| // output picture and blitting them. These callbacks will not be made unless |
| // Initialize() has returned successfully. |
| // This interface is extended by the various layers that relay messages back |
| // to the plugin, through the PPP_VideoDecoder_Dev interface the plugin |
| // implements. |
| class MEDIA_EXPORT Client { |
| public: |
| // Notify the client that deferred initialization has completed successfully |
| // or not. This is required if and only if deferred initialization is |
| // supported by the VDA (see Capabilities), and it is supported by the |
| // client (see Config::is_deferred_initialization_allowed), and the initial |
| // call to VDA::Initialize returns true. |
| // The default implementation is a NOTREACHED, since deferred initialization |
| // is not supported by default. |
| virtual void NotifyInitializationComplete(Status status); |
| |
| // Callback to tell client how many and what size of buffers to provide. |
| // Note that the actual count provided through AssignPictureBuffers() can be |
| // larger than the value requested. |
| // |format| indicates what format the decoded frames will be produced in |
| // by the VDA, or PIXEL_FORMAT_UNKNOWN if the underlying platform handles |
| // this transparently. |
| virtual void ProvidePictureBuffers(uint32_t requested_num_of_buffers, |
| VideoPixelFormat format, |
| uint32_t textures_per_buffer, |
| const gfx::Size& dimensions, |
| uint32_t texture_target) = 0; |
| |
| // This is the same as ProvidePictureBuffers() except that |visible_rect| is |
| // also included. The default implementation calls ProvidePictureBuffers() |
| // setting |dimensions| = GetRectSizeFromOrigin(|visible_rect|) when |
| // |texture_target| is GL_TEXTURE_EXTERNAL_OES; otherwise, it passes along |
| // all parameters to ProvidePictureBuffers() as they are. |
| virtual void ProvidePictureBuffersWithVisibleRect( |
| uint32_t requested_num_of_buffers, |
| VideoPixelFormat format, |
| uint32_t textures_per_buffer, |
| const gfx::Size& dimensions, |
| const gfx::Rect& visible_rect, |
| uint32_t texture_target); |
| |
| // Callback to dismiss picture buffer that was assigned earlier. |
| virtual void DismissPictureBuffer(int32_t picture_buffer_id) = 0; |
| |
| // Callback to deliver decoded pictures ready to be displayed. |
| // Note: the decoded pictures might be sent to the client more than once. |
| // The client should call ReusePictureBuffer() once for each PictureReady(). |
| // For example, VDA calls Client::PictureReady() twice for a picture buffer. |
| // Then the client should also call VDA::ReusePictureBuffer() twice. |
| // Until that, VDA cannot reuse the picture buffer. |
| virtual void PictureReady(const Picture& picture) = 0; |
| |
| // Callback to notify that decoded has decoded the end of the current |
| // bitstream buffer. |
| virtual void NotifyEndOfBitstreamBuffer(int32_t bitstream_buffer_id) = 0; |
| |
| // Flush completion callback. |
| virtual void NotifyFlushDone() = 0; |
| |
| // Reset completion callback. |
| virtual void NotifyResetDone() = 0; |
| |
| // Callback to notify about decoding errors. Note that errors in |
| // Initialize() will not be reported here, but will instead be indicated by |
| // a false return value there. |
| virtual void NotifyError(Error error) = 0; |
| |
| // Return the SharedImageStub through which SharedImages may be created. |
| // Default implementation returns nullptr. |
| virtual gpu::SharedImageStub* GetSharedImageStub() const; |
| |
| // Return the CommandBufferHelper through which GL passthrough textures may |
| // be created. Default implementation returns nullptr. |
| virtual CommandBufferHelper* GetCommandBufferHelper() const; |
| |
| protected: |
| virtual ~Client() {} |
| }; |
| |
| // Video decoder functions. |
| |
| // Initializes the video decoder with specific configuration. Called once per |
| // decoder construction. This call is synchronous and returns true iff |
| // initialization is successful, unless deferred initialization is used. |
| // |
| // By default, deferred initialization is not used. However, if Config:: |
| // is_deferred_initialization_allowed is set by the client, and if |
| // Capabilities::Flags::SUPPORTS_DEFERRED_INITIALIZATION is set by the VDA, |
| // and if VDA::Initialize returns true, then the client can expect a call to |
| // NotifyInitializationComplete with the actual success / failure of |
| // initialization. Note that a return value of false from VDA::Initialize |
| // indicates that initialization definitely failed, and no callback is needed. |
| // |
| // For encrypted video, only deferred initialization is supported and |config| |
| // must contain a valid |cdm_id|. |
| // |
| // Parameters: |
| // |config| contains the initialization parameters. |
| // |client| is the client of this video decoder. Does not take ownership of |
| // |client| which must be valid until Destroy() is called. |
| virtual bool Initialize(const Config& config, Client* client) = 0; |
| |
| // Decodes given bitstream buffer that contains at most one frame. Once |
| // decoder is done with processing |bitstream_buffer| it will call |
| // NotifyEndOfBitstreamBuffer() with the bitstream buffer id. |
| // Parameters: |
| // |bitstream_buffer| is the input bitstream that is sent for decoding. |
| virtual void Decode(BitstreamBuffer bitstream_buffer) = 0; |
| |
| // Decodes given decoder buffer that contains at most one frame. Once |
| // decoder is done with processing |buffer| it will call |
| // NotifyEndOfBitstreamBuffer() with the bitstream id. |
| // Parameters: |
| // |buffer| is the input buffer that is sent for decoding. |
| // |bitstream_id| identifies the buffer for PictureReady() and |
| // NotifyEndOfBitstreamBuffer() |
| virtual void Decode(scoped_refptr<DecoderBuffer> buffer, |
| int32_t bitstream_id); |
| |
| // Assigns a set of texture-backed picture buffers to the video decoder. |
| // |
| // Ownership of each picture buffer remains with the client, but the client |
| // is not allowed to deallocate the buffer before the DismissPictureBuffer |
| // callback has been initiated for a given buffer. |
| // |
| // Parameters: |
| // |buffers| contains the allocated picture buffers for the output. Note |
| // that the count of buffers may be larger than the count requested through |
| // the call to Client::ProvidePictureBuffers(). |
| virtual void AssignPictureBuffers( |
| const std::vector<PictureBuffer>& buffers) = 0; |
| |
| // Imports |gpu_memory_buffer_handle|, pointing to a buffer in |pixel_format|, |
| // as backing memory for picture buffer associated with |picture_buffer_id|. |
| // This can only be be used if the VDA has been Initialize()d with |
| // config.output_mode = IMPORT, and should be preceded by a call to |
| // AssignPictureBuffers() to set up the number of PictureBuffers and their |
| // details. |
| // The |pixel_format| used here may be different from the |pixel_format| |
| // required in ProvidePictureBuffers(). If the buffer cannot be imported an |
| // error should be notified via NotifyError(). |
| // After this call, the VDA becomes the owner of the GpuMemoryBufferHandle, |
| // and is responsible for closing it after use, also on import failure. |
| virtual void ImportBufferForPicture( |
| int32_t picture_buffer_id, |
| VideoPixelFormat pixel_format, |
| gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle); |
| |
| // Sends picture buffers to be reused by the decoder. This needs to be called |
| // for each buffer that has been processed so that decoder may know onto which |
| // picture buffers it can write the output to. |
| // Note: the decoded pictures might be sent to the client more than once. |
| // The client should call ReusePictureBuffer() once for each PictureReady(). |
| // For example, VDA calls Client::PictureReady() twice for a picture buffer. |
| // Then the client should also call VDA::ReusePictureBuffer() twice. |
| // Until that, VDA can really reuse the picture buffer. |
| // |
| // Parameters: |
| // |picture_buffer_id| id of the picture buffer that is to be reused. |
| virtual void ReusePictureBuffer(int32_t picture_buffer_id) = 0; |
| |
| // Flushes the decoder: all pending inputs will be decoded and pictures handed |
| // back to the client, followed by NotifyFlushDone() being called on the |
| // client. Can be used to implement "end of stream" notification. |
| virtual void Flush() = 0; |
| |
| // Resets the decoder: all pending inputs are dropped immediately and the |
| // decoder returned to a state ready for further Decode()s, followed by |
| // NotifyResetDone() being called on the client. Can be used to implement |
| // "seek". After Flush is called, it is OK to call Reset before receiving |
| // NotifyFlushDone() and VDA should cancel the flush. Note NotifyFlushDone() |
| // may be on the way to the client. If client gets NotifyFlushDone(), it |
| // should be before NotifyResetDone(). |
| virtual void Reset() = 0; |
| |
| // An optional graphics surface that the VDA should render to. For setting |
| // an output SurfaceView on Android. Passing |kNoSurfaceID| will clear any |
| // previously set surface in favor of an internally generated texture. |
| // |routing_token| is an optional AndroidOverlay routing token. At most one |
| // should be non-empty. |
| virtual void SetOverlayInfo(const OverlayInfo& overlay_info); |
| |
| // Destroys the decoder: all pending inputs are dropped immediately and the |
| // component is freed. This call may asynchornously free system resources, |
| // but its client-visible effects are synchronous. After this method returns |
| // no more callbacks will be made on the client. Deletes |this| |
| // unconditionally, so make sure to drop all pointers to it! |
| virtual void Destroy() = 0; |
| |
| // TO BE CALLED IN THE SAME PROCESS AS THE VDA IMPLEMENTATION ONLY. |
| // |
| // A decode "task" is a sequence that includes a Decode() call from Client, |
| // as well as corresponding callbacks to return the input BitstreamBuffer |
| // after use, and the resulting output Picture(s). |
| // |
| // If the Client can support running these three calls on a separate thread, |
| // it may call this method to try to set up the VDA implementation to do so. |
| // If the VDA can support this as well, return true, otherwise return false. |
| // If true is returned, the client may submit each Decode() call (but no other |
| // calls) on |decode_task_runner|, and should then expect that |
| // NotifyEndOfBitstreamBuffer() and PictureReady() callbacks may come on |
| // |decode_task_runner| as well, called on |decode_client|, instead of client |
| // provided to Initialize(). |
| // |
| // This method may be called at any time. |
| // |
| // NOTE 1: some callbacks may still have to come on the main thread and the |
| // Client should handle both callbacks coming on main and |decode_task_runner| |
| // thread. |
| // |
| // NOTE 2: VDA implementations of Decode() must return as soon as possible and |
| // never block, as |decode_task_runner| may be a latency critical thread |
| // (such as the GPU IO thread). |
| // |
| // One application of this is offloading the GPU Child thread. In general, |
| // calls to VDA in GPU process have to be done on the GPU Child thread, as |
| // they may require GL context to be current. However, some VDAs may be able |
| // to run decode operations without GL context, which helps reduce latency and |
| // offloads the GPU Child thread. |
| virtual bool TryToSetupDecodeOnSeparateThread( |
| const base::WeakPtr<Client>& decode_client, |
| const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner); |
| |
| // Windows creates a BGRA texture. |
| // TODO(dshwang): after moving to D3D11, remove this. crbug.com/438691 |
| virtual GLenum GetSurfaceInternalFormat() const; |
| |
| // Returns true if the decoder supports SharedImage backed picture buffers. |
| // May be called on any thread at any time. |
| virtual bool SupportsSharedImagePictureBuffers() const; |
| |
| enum class TextureAllocationMode { |
| kDoNotAllocateGLTextures, |
| kAllocateGLTextures |
| }; |
| |
| // Returns an enum used to allocate GL textures for shared images. |
| // May be called on any thread at any time. |
| virtual TextureAllocationMode GetSharedImageTextureAllocationMode() const; |
| |
| protected: |
| // Do not delete directly; use Destroy() or own it with a scoped_ptr, which |
| // will Destroy() it properly by default. |
| virtual ~VideoDecodeAccelerator(); |
| }; |
| |
| } // namespace media |
| |
| namespace std { |
| |
| // Specialize std::default_delete so that |
| // std::unique_ptr<VideoDecodeAccelerator> uses "Destroy()" instead of trying to |
| // use the destructor. |
| template <> |
| struct MEDIA_EXPORT default_delete<media::VideoDecodeAccelerator> { |
| void operator()(media::VideoDecodeAccelerator* vda) const; |
| }; |
| |
| } // namespace std |
| |
| #endif // MEDIA_VIDEO_VIDEO_DECODE_ACCELERATOR_H_ |