Skip to content

Commit

Permalink
Added timestamp to new frame callback + added FPS counter to test app.
Browse files Browse the repository at this point in the history
  • Loading branch information
sskodje committed Sep 13, 2022
1 parent 21da956 commit 2f6cecd
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 68 deletions.
4 changes: 3 additions & 1 deletion ScreenRecorderLib/Callback.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,10 @@ namespace ScreenRecorderLib {
public ref class FrameRecordedEventArgs :System::EventArgs {
public:
property int FrameNumber;
FrameRecordedEventArgs(int frameNumber) {
property INT64 Timestamp;
FrameRecordedEventArgs(int frameNumber, INT64 timestamp) {
FrameNumber = frameNumber;
Timestamp = timestamp;
}
};
}
4 changes: 2 additions & 2 deletions ScreenRecorderLib/Recorder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -858,8 +858,8 @@ void ScreenRecorderLib::Recorder::EventSnapshotCreated(std::wstring str)
OnSnapshotSaved(this, gcnew SnapshotSavedEventArgs(gcnew String(str.c_str())));
}

void Recorder::FrameNumberChanged(int newFrameNumber)
void Recorder::FrameNumberChanged(int newFrameNumber, INT64 timestamp)
{
OnFrameRecorded(this, gcnew FrameRecordedEventArgs(newFrameNumber));
OnFrameRecorded(this, gcnew FrameRecordedEventArgs(newFrameNumber,timestamp));
CurrentFrameNumber = newFrameNumber;
}
4 changes: 2 additions & 2 deletions ScreenRecorderLib/Recorder.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ delegate void InternalStatusCallbackDelegate(int status);
delegate void InternalCompletionCallbackDelegate(std::wstring path, nlohmann::fifo_map<std::wstring, int>);
delegate void InternalErrorCallbackDelegate(std::wstring error, std::wstring path);
delegate void InternalSnapshotCallbackDelegate(std::wstring path);
delegate void InternalFrameNumberCallbackDelegate(int newFrameNumber);
delegate void InternalFrameNumberCallbackDelegate(int newFrameNumber, INT64 timestamp);

namespace ScreenRecorderLib {

Expand Down Expand Up @@ -65,7 +65,7 @@ namespace ScreenRecorderLib {
void EventFailed(std::wstring error, std::wstring path);
void EventStatusChanged(int status);
void EventSnapshotCreated(std::wstring str);
void FrameNumberChanged(int newFrameNumber);
void FrameNumberChanged(int newFrameNumber, INT64 timestamp);
void SetupCallbacks();
void ClearCallbacks();
static HRESULT CreateNativeRecordingSource(_In_ RecordingSourceBase^ managedSource, _Out_ RECORDING_SOURCE* pNativeSource);
Expand Down
5 changes: 3 additions & 2 deletions ScreenRecorderLibNative/RecordingManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ void RecordingManager::CleanupDxResources()
#if _DEBUG
if (m_DxResources.Debug) {
m_DxDebugMutex.lock();
m_DxResources.Debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL| D3D11_RLDO_IGNORE_INTERNAL);
m_DxResources.Debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL | D3D11_RLDO_IGNORE_INTERNAL);
m_DxDebugMutex.unlock();
SafeRelease(&m_DxResources.Debug);
}
Expand Down Expand Up @@ -502,7 +502,8 @@ REC_RESULT RecordingManager::StartRecorderLoop(_In_ const std::vector<RECORDING_
RETURN_ON_BAD_HR(renderHr = m_EncoderResult = m_OutputManager->RenderFrame(model));
frameNr++;
if (RecordingFrameNumberChangedCallback != nullptr && !m_IsDestructing) {
RecordingFrameNumberChangedCallback(frameNr);
INT64 timestamp = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
RecordingFrameNumberChangedCallback(frameNr, timestamp);
}
havePrematureFrame = false;
lastFrameStartPos100Nanos += duration100Nanos;
Expand Down
2 changes: 1 addition & 1 deletion ScreenRecorderLibNative/RecordingManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ typedef void(__stdcall *CallbackCompleteFunction)(std::wstring, nlohmann::fifo_m
typedef void(__stdcall *CallbackStatusChangedFunction)(int);
typedef void(__stdcall *CallbackErrorFunction)(std::wstring, std::wstring);
typedef void(__stdcall *CallbackSnapshotFunction)(std::wstring);
typedef void(__stdcall *CallbackFrameNumberChangedFunction)(int);
typedef void(__stdcall *CallbackFrameNumberChangedFunction)(int, INT64);

#define STATUS_IDLE 0
#define STATUS_RECORDING 1
Expand Down
14 changes: 7 additions & 7 deletions TestApp/App.config
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Vlc.DotNet.Core" publicKeyToken="84529da31f4eb963" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="0.0.0.0" />
<assemblyIdentity name="Vlc.DotNet.Core" publicKeyToken="84529da31f4eb963" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="0.0.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Vlc.DotNet.Core.Interops" publicKeyToken="84529da31f4eb963" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="0.0.0.0" />
<assemblyIdentity name="Vlc.DotNet.Core.Interops" publicKeyToken="84529da31f4eb963" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="0.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
</configuration>
23 changes: 16 additions & 7 deletions TestApp/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -1207,13 +1207,22 @@
HorizontalAlignment="Center"
x:Name="TimeStampTextBlock"
Margin="10,0" />
<TextBlock FontSize="18"
Text="{Binding ElementName=MainWin,Path=CurrentFrameNumber, StringFormat={}Frame: {0}}"
Margin="10,0"
TextWrapping="NoWrap"
HorizontalAlignment="Center"
Visibility="Collapsed"
x:Name="FrameNumberTextBlock" />
<StackPanel Orientation="Vertical"
HorizontalAlignment="Center"
x:Name="FrameNumberPanel"
Visibility="Collapsed">
<TextBlock x:Name="FrameNumberTextBlock"
DataContext="{Binding ElementName=MainWin}"
FontSize="16">
<TextBlock.Text>
<MultiBinding StringFormat="{}Frame: {0} | Avg FPS: {1:0.0} | FPS: {2:0.0}">
<Binding Path="CurrentFrameNumber" />
<Binding Path="AverageFrameRate" />
<Binding Path="CurrentFrameRate" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
<TextBlock FontSize="32"
Text="Idle"
HorizontalAlignment="Center"
Expand Down
47 changes: 41 additions & 6 deletions TestApp/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public partial class MainWindow : Window, INotifyPropertyChanged
{
private Recorder _rec;
private DispatcherTimer _progressTimer;
private readonly List<long> _recordedFrameTimes = new List<long>();
private DateTimeOffset? _recordingStartTime = null;
private DateTimeOffset? _recordingPauseTime = null;
private Stream _outputStream;
Expand Down Expand Up @@ -183,6 +184,35 @@ public int CurrentFrameNumber
}
}

private double _averageFrameRate;
public double AverageFrameRate
{
get { return _averageFrameRate; }
set
{
if (_averageFrameRate != value)
{
_averageFrameRate = value;
RaisePropertyChanged(nameof(AverageFrameRate));
}
}
}

private double _currentFrameRate;
public double CurrentFrameRate
{
get { return _currentFrameRate; }
set
{
if (_currentFrameRate != value)
{
_currentFrameRate = value;
RaisePropertyChanged(nameof(CurrentFrameRate));
}
}
}


public H264Profile CurrentH264Profile { get; set; } = H264Profile.High;
public H265Profile CurrentH265Profile { get; set; } = H265Profile.Main;

Expand Down Expand Up @@ -212,7 +242,7 @@ private void MainWindow_PropertyChanged(object sender, PropertyChangedEventArgs
}
}
}

private void RecordingSource_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
Expand Down Expand Up @@ -539,6 +569,7 @@ private void Rec_OnFrameRecorded(object sender, FrameRecordedEventArgs e)
Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
{
CurrentFrameNumber = e.FrameNumber;
_recordedFrameTimes.Add(e.Timestamp);
}));
}

Expand Down Expand Up @@ -696,9 +727,7 @@ private void Rec_OnStatusChanged(object sender, RecordingStatusEventArgs e)
case RecorderStatus.Recording:
_recordingStartTime = DateTimeOffset.Now;
PauseButton.Visibility = Visibility.Visible;
this.FrameNumberTextBlock.Visibility = Visibility.Visible;
if (_progressTimer != null)
_progressTimer.IsEnabled = true;
this.FrameNumberPanel.Visibility = Visibility.Visible;
if (_recordingPauseTime != null)
{
_recordingStartTime = _recordingStartTime.Value.AddTicks((DateTimeOffset.Now.Subtract(_recordingPauseTime.Value)).Ticks);
Expand All @@ -717,8 +746,7 @@ private void Rec_OnStatusChanged(object sender, RecordingStatusEventArgs e)
_progressTimer.Start();
break;
case RecorderStatus.Paused:
if (_progressTimer != null)
_progressTimer.IsEnabled = false;
_progressTimer?.Stop();
_recordingPauseTime = DateTimeOffset.Now;
PauseButton.Content = "Resume";
this.StatusTextBlock.Text = "Paused";
Expand All @@ -736,6 +764,13 @@ private void Rec_OnStatusChanged(object sender, RecordingStatusEventArgs e)
private void ProgressTimer_Tick(object sender, EventArgs e)
{
UpdateProgress();
if (_recordedFrameTimes.Count > 0)
{
AverageFrameRate = CurrentFrameNumber / DateTimeOffset.FromUnixTimeMilliseconds(_recordedFrameTimes.Last()).Subtract(_recordingStartTime.Value).TotalSeconds;
_recordedFrameTimes.RemoveRange(0, Math.Max(0, _recordedFrameTimes.Count - 10));
double intervalMillis = (double)(_recordedFrameTimes.Last() - _recordedFrameTimes.First());
CurrentFrameRate = (_recordedFrameTimes.Count-1) / (double)intervalMillis * 1000;
}
}
private void UpdateProgress()
{
Expand Down
44 changes: 18 additions & 26 deletions TestApp/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 9 additions & 13 deletions TestApp/Properties/Settings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion TestApp/TestApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TestApp</RootNamespace>
<AssemblyName>TestApp</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
Expand Down

0 comments on commit 2f6cecd

Please sign in to comment.