// 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. // Note: ported from Chromium commit head: 85fdf90 #ifndef VIDEO_DECODE_ACCELERATOR_H_ #define VIDEO_DECODE_ACCELERATOR_H_ #include <vector> #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "bitstream_buffer.h" #include "native_pixmap_handle.h" #include "picture.h" #include "size.h" #include "video_codecs.h" #include "video_pixel_format.h" namespace base { class SingleThreadTaskRunner; } namespace media { // Video decoder interface. // This interface is extended by the various components that ultimately // implement the backend of PPB_VideoDecoder_Dev. class VideoDecodeAccelerator { public: // Specification of a decoding profile supported by an decoder. // |max_resolution| and |min_resolution| are inclusive. struct SupportedProfile { SupportedProfile(); ~SupportedProfile(); VideoCodecProfile profile; Size max_resolution; Size min_resolution; bool encrypted_only; }; using SupportedProfiles = std::vector<SupportedProfile>; struct 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 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; // The video codec and profile. VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; // Whether the client supports deferred initialization. bool is_deferred_initialization_allowed = false; // Coded size of the video frame hint, subject to change. Size initial_expected_coded_size = 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; }; // 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 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(bool success); // 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, const Size& dimensions) = 0; // 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. 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; 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(const BitstreamBuffer& bitstream_buffer) = 0; // 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 those file descriptors, // and is responsible for closing it after use, also on import failure. virtual void ImportBufferForPicture( int32_t picture_buffer_id, VideoPixelFormat pixel_format, const NativePixmapHandle& native_pixmap_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. // // 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; // 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); 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 default_delete<media::VideoDecodeAccelerator> { void operator()(media::VideoDecodeAccelerator* vda) const; }; } // namespace std #endif // VIDEO_DECODE_ACCELERATOR_H_