Files
UnrealEngine/Engine/Plugins/Media/ElectraPlayer/Source/ElectraPlayerRuntime/Private/ElectraPlayerAudioDecoderOutput.cpp
2025-05-18 13:04:45 +08:00

151 lines
3.5 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "MediaAudioDecoderOutput.h"
#include "Renderer/RendererAudio.h"
class FElectraPlayerAudioDecoderOutput : public IAudioDecoderOutput
{
public:
FElectraPlayerAudioDecoderOutput() = default;
~FElectraPlayerAudioDecoderOutput() override
{
Reserve(0);
}
void Reserve(uint32 InBufferSizeBytes) override final
{
if (InBufferSizeBytes != BufferMaxSizeBytes)
{
if (Buffer)
{
FMemory::Free(Buffer);
Buffer = nullptr;
}
BufferMaxSizeBytes = InBufferSizeBytes;
if (BufferMaxSizeBytes)
{
Buffer = FMemory::Malloc(InBufferSizeBytes);
check(Buffer);
}
}
}
void SetOwner(const TSharedPtr<IDecoderOutputOwner, ESPMode::ThreadSafe>& Renderer) override
{
OwningRenderer = Renderer;
}
void Initialize(ESampleFormat InFormat, uint32 InNumChannels, uint32 InSampleRate, FTimespan InDuration, const FDecoderTimeStamp& InPts, uint32 InBufferSizeBytes) override
{
check(BufferMaxSizeBytes >= InBufferSizeBytes);
Format = InFormat;
NumChannels = InNumChannels;
SampleRate = InSampleRate;
Time = InPts;
Duration = InDuration;
BufferUsedSizeBytes = InBufferSizeBytes;
}
const void* GetBuffer() const override
{
return Buffer;
}
uint32 GetUsedBufferBytes() const override
{
return BufferUsedSizeBytes;
}
uint32 GetReservedBufferBytes() const override
{
return BufferMaxSizeBytes;
}
uint32 GetChannels() const override
{
return NumChannels;
}
uint32 GetFrames() const override
{
if (Format == ESampleFormat::Undefined)
{
return 0;
}
check((int32)Format <= (int32)ESampleFormat::Int32);
static_assert((int32)ESampleFormat::Undefined == 0, "Check order of enum");
static_assert((int32)ESampleFormat::Double == 1, "Check order of enum");
static_assert((int32)ESampleFormat::Float == 2, "Check order of enum");
static_assert((int32)ESampleFormat::Int8 == 3, "Check order of enum");
static_assert((int32)ESampleFormat::Int16 == 4, "Check order of enum");
static_assert((int32)ESampleFormat::Int32 == 5, "Check order of enum");
static const uint32 _SampleSize[] = {0, 8, 4, 1, 2, 4};
return BufferUsedSizeBytes / (NumChannels * _SampleSize[(uint32)Format]);
}
ESampleFormat GetFormat() const override
{
return Format;
}
FDecoderTimeStamp GetTime() const override
{
return Time;
}
FTimespan GetDuration() const override
{
return Duration;
}
uint32 GetSampleRate() const override
{
return SampleRate;
}
void SetTime(const FDecoderTimeStamp& InTime) override
{
Time = InTime;
}
void ShutdownPoolable() override
{
TSharedPtr<IDecoderOutputOwner, ESPMode::ThreadSafe> lockedAudioRenderer = OwningRenderer.Pin();
if (lockedAudioRenderer.IsValid())
{
lockedAudioRenderer->SampleReleasedToPool(this);
}
}
private:
uint32 BufferMaxSizeBytes = 0;
uint32 BufferUsedSizeBytes = 0;
void* Buffer = nullptr;
ESampleFormat Format = ESampleFormat::Undefined;
uint32 NumChannels = 0;
uint32 SampleRate = 0;
FDecoderTimeStamp Time;
FTimespan Duration;
TWeakPtr<IDecoderOutputOwner, ESPMode::ThreadSafe> OwningRenderer;
};
// =================================================================================================================================
/*
Create one and the same audio sample for all platforms - we so far do not need any specialization here (otherwise this should be with the respective decoder - much like the class definition / impl above)
*/
IAudioDecoderOutput* FElectraPlayerPlatformAudioDecoderOutputFactory::Create()
{
return new FElectraPlayerAudioDecoderOutput();
}