// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreTypes.h" #include "Core/MediaTypes.h" #include "PlayerTime.h" #include "ParameterDictionary.h" #include "MediaDecoderOutput.h" namespace Electra { class IMediaRenderClock { public: virtual ~IMediaRenderClock() = default; enum class ERendererType { Video, Audio, Subtitles, }; /** * Called by the renderer to set the time of the most sample that has been output most recently. * * @param ForRenderer * Identifies the type of renderer from which the time is set. * @param CurrentRenderTime * The time of the sample most recently output. */ virtual void SetCurrentTime(ERendererType ForRenderer, const FTimeValue& CurrentRenderTime) = 0; /** * Gets the current _interpolated_ sample output time from the last * time SetCurrentTime() was called plus the elapsed time since then. * * @param FromRenderer * Identifies the type of renderer for which to get the time. * * @return Interpolated render time */ virtual FTimeValue GetInterpolatedRenderTime(ERendererType FromRenderer) = 0; }; class IMediaRenderer : public IDecoderOutputOwner { public: virtual ~IMediaRenderer() = default; /** * Buffer interface */ class IBuffer { public: virtual ~IBuffer() = default; /** * Returns the properties of the buffer. * * @return Const reference to the dictionary containing buffer properties. */ virtual const FParamDict& GetBufferProperties() const = 0; // Same, but returns the writable dictionary. Use with caution. virtual FParamDict& GetMutableBufferProperties() = 0; }; //================================================================================================================= // Methods called from both a decoder and the player from their respective threads. // /** * Returns the properties of the buffer pool. Those properties should not change * during the lifetime of the pool. * A mandatory property is the maximum number of buffers that can be obtained from * the pool ("max_buffers":int64). * * @return Const reference to the dictionary containing buffer pool properties. */ virtual const FParamDict& GetBufferPoolProperties() const = 0; //================================================================================================================= // Methods called from a decoder (and from within the decoder thread) // /** * Create a buffer pool from where a decoder can get the block of memory to decode into. * * @param Parameters Dictionary with create options depending on the type of * render buffers to create (video or audio) * * @return One of UEMEDIA_ERROR_OK, UEMEDIA_ERROR_BAD_ARGUMENTS or UEMEDIA_ERROR_OOM (or others if warranted). */ virtual UEMediaError CreateBufferPool(const FParamDict& Parameters) = 0; /** * Asks for a sample buffer from the buffer pool created previously through CreateBufferPool(). * * @param OutBuffer Receives the address of the returned IBuffer * @param TimeoutInMicroseconds * Maximum time to wait for a buffer to become available before giving up. * If 0 a "peek" if a buffer is available is to be performed and a buffer * returned if one is available. * No value indicates an infinite wait time! * @param InParameters * Optional parameters for buffer properties if different from those to CreateBufferPool(). * * @return One of UEMEDIA_ERROR_OK, UEMEDIA_ERROR_BAD_ARGUMENTS or UEMEDIA_ERROR_INSUFFICIENT_DATA. * Other values if warranted but those will cause a playback error. */ virtual UEMediaError AcquireBuffer(IBuffer*& OutBuffer, int32 TimeoutInMicroseconds, const FParamDict& InParameters) = 0; /** * Releases the buffer for rendering and subsequent return to the buffer pool. * * @param Buffer The buffer being returned to the renderer for rendering. * @param bRender true to render the contents of the buffer, false to discard them. * @param InSampleProperties * Properties of the decoded sample (eg. width and height for video, sample rate for audio) * * @return Should be UEMEDIA_ERROR_OK only. Anything else will cause a playback error (like UEMEDIA_ERROR_BAD_ARGUMENTS for bad properties) */ virtual UEMediaError ReturnBuffer(IBuffer* Buffer, bool bRender, FParamDict& InOutSampleProperties) = 0; /** * Informs that the decoder is done with this pool. This only indicates no calls to * GetBuffer() and ReleaseBuffer() will be made by this decoder instance any more. * It is up to the renderer to decide whether or not to destroy the pool or keep it * around for re-use with a new decoder instance (the next CreateBufferPool() call). * * @return Should be UEMEDIA_ERROR_OK only. Anything else will cause a playback error. */ virtual UEMediaError ReleaseBufferPool() = 0; /** * Returns if the renderer's output queues are ready to receive any output from a decode * * @return True if ready, false if decode should be delayed. */ virtual bool CanReceiveOutputFrames(uint64 NumFrames) const = 0; /** * Returns how many frames of ready to use data the renderer has in its queue. * * @return True if information is available, false if not. */ virtual bool GetEnqueuedFrameInfo(int32& OutNumberOfEnqueuedFrames, FTimeValue& OutDurationOfEnqueuedFrames) const = 0; //================================================================================================================= // Methods called from the player (and from within the player thread) // /** * Sets the render clock which this renderer needs to update with the presentation time * of the most recently rendered sample. * * @param RenderClock * Render clock to update with the most recent output sample time. */ virtual void SetRenderClock(TSharedPtr RenderClock) = 0; /** * Called if this renderer is being wrapped by another renderer. */ virtual void SetParentRenderer(TWeakPtr ParentRenderer) = 0; /** * Sets the next expected sample's approximate presentation time stamp. * This is called as data buffering begins at the indicated play start * position. The actual timestamp of the first sample will vary. * The renderer can ignore this value and rely only on the timestamp * of the decoded sample. * * @param NextApproxPTS * Approximate timestamp at which playback is about to commence. */ virtual void SetNextApproximatePresentationTime(const FTimeValue& NextApproxPTS) = 0; /** * Flushes all pending buffers not yet rendered. * There should be no outstanding buffers the decoder has not yet released. * Options may indicate to hold the current frame on-screen (for video) or * to tear it down. * * @param InOptions Options indicating flush operation, like keeping the current video frame on-screen. * * @return Should be UEMEDIA_ERROR_OK only. * If there are still frames a decoder has not returned yet UEMEDIA_ERROR_INTERNAL should be returned. * Any failure will cause a playback error. */ virtual UEMediaError Flush(const FParamDict& InOptions) = 0; /** * Begins rendering of the first sample buffer. * * @param InOptions Reserved for future use. */ virtual void StartRendering(const FParamDict& InOptions) = 0; /** * Stops rendering of sample buffers. * * @param InOptions Reserved for future use. */ virtual void StopRendering(const FParamDict& InOptions) = 0; }; namespace RenderOptionKeys { static const FName ValidityValue(TEXT("$renderVV$")); static const FName Duration(TEXT("duration")); static const FName PTS(TEXT("pts")); static const FName EOSFlag(TEXT("eos")); static const FName DummyBufferFlag(TEXT("is_dummy")); static const FName Texture(TEXT("texture")); static const FName AllocatedAddress(TEXT("address")); static const FName AllocatedSize(TEXT("size")); static const FName MaxBuffers(TEXT("max_buffers")); static const FName MaxBufferSize(TEXT("max_buffer_size")); static const FName NumBuffers(TEXT("num_buffers")); static const FName UsedByteSize(TEXT("byte_size")); static const FName MaxChannels(TEXT("max_channels")); static const FName NumChannels(TEXT("num_channels")); static const FName SamplesPerBlock(TEXT("samples_per_block")); static const FName SampleRate(TEXT("sample_rate")); } } // namespace Electra