Files
UnrealEngine/Engine/Source/Runtime/Media/Private/MediaClock.cpp
2025-05-18 13:04:45 +08:00

178 lines
3.0 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "MediaClock.h"
#include "CoreTypes.h"
#include "IMediaClockSink.h"
#include "Misc/ScopeLock.h"
/* FMediaClock structors
*****************************************************************************/
FMediaClock::FMediaClock()
: DeltaTime(FTimespan::Zero())
, Timecode(FTimespan::MinValue())
{ }
/* FMediaClock interface
*****************************************************************************/
void FMediaClock::TickFetch()
{
UpdateSinkArray();
for (int32 SinkIndex = Sinks.Num() - 1; SinkIndex >= 0; --SinkIndex)
{
auto Sink = Sinks[SinkIndex].Pin();
if (Sink.IsValid())
{
Sink->TickFetch(DeltaTime, Timecode);
}
else
{
Sinks.RemoveAtSwap(SinkIndex);
}
}
}
void FMediaClock::TickInput()
{
UpdateSinkArray();
for (int32 SinkIndex = Sinks.Num() - 1; SinkIndex >= 0; --SinkIndex)
{
auto Sink = Sinks[SinkIndex].Pin();
if (Sink.IsValid())
{
Sink->TickInput(DeltaTime, Timecode);
}
else
{
Sinks.RemoveAtSwap(SinkIndex);
}
}
}
void FMediaClock::TickOutput()
{
UpdateSinkArray();
for (int32 SinkIndex = Sinks.Num() - 1; SinkIndex >= 0; --SinkIndex)
{
auto Sink = Sinks[SinkIndex].Pin();
if (Sink.IsValid())
{
Sink->TickOutput(DeltaTime, Timecode);
}
else
{
Sinks.RemoveAtSwap(SinkIndex);
}
}
}
void FMediaClock::TickRender()
{
UpdateSinkArray();
for (int32 SinkIndex = Sinks.Num() - 1; SinkIndex >= 0; --SinkIndex)
{
auto Sink = Sinks[SinkIndex].Pin();
if (Sink.IsValid())
{
Sink->TickRender(DeltaTime, Timecode);
}
else
{
Sinks.RemoveAtSwap(SinkIndex);
}
}
}
void FMediaClock::UpdateTimecode(const FTimespan NewTimecode, bool NewTimecodeLocked)
{
if (Timecode == FTimespan::MinValue())
{
DeltaTime = FTimespan::Zero();
}
else
{
DeltaTime = NewTimecode - Timecode;
}
Timecode = NewTimecode;
TimecodeLocked = NewTimecodeLocked;
}
/* IMediaClock interface
*****************************************************************************/
void FMediaClock::AddSink(const TSharedRef<IMediaClockSink, ESPMode::ThreadSafe>& Sink)
{
FScopeLock Lock(&SinkCriticalSection);
SinksToAdd.AddUnique(Sink);
// Just in case this sink is pending to be removed.
if (SinksToRemove.Contains(Sink))
{
SinksToRemove.RemoveSwap(Sink);
}
}
FTimespan FMediaClock::GetTimecode() const
{
return Timecode;
}
bool FMediaClock::IsTimecodeLocked() const
{
return TimecodeLocked;
}
void FMediaClock::RemoveSink(const TSharedRef<IMediaClockSink, ESPMode::ThreadSafe>& Sink)
{
FScopeLock Lock(&SinkCriticalSection);
SinksToRemove.AddUnique(Sink);
// Just in case this sink is pending to be added.
if (SinksToAdd.Contains(Sink))
{
SinksToAdd.RemoveSwap(Sink);
}
}
void FMediaClock::UpdateSinkArray()
{
FScopeLock Lock(&SinkCriticalSection);
// Add new sinks.
for (auto Sink : SinksToAdd)
{
Sinks.AddUnique(Sink);
}
SinksToAdd.Empty();
// Remove sinks.
for (auto Sink : SinksToRemove)
{
Sinks.RemoveSwap(Sink);
}
SinksToRemove.Empty();
}