Skip to content

Commit

Permalink
Merge branch 'master' into fix_tcp_socket_crash
Browse files Browse the repository at this point in the history
  • Loading branch information
KirisameMarisa committed Mar 8, 2024
2 parents 620aeec + fa75827 commit 4ae1bbc
Show file tree
Hide file tree
Showing 36 changed files with 751 additions and 247 deletions.
9 changes: 9 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ jobs:
steps:
- uses: actions/checkout@v3

- name: Checkout submodules
run: git submodule update --init --recursive

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
Expand All @@ -36,6 +39,9 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v3

- name: Checkout submodules
run: git submodule update --init --recursive

- name: Setup .NET on Windows
uses: actions/setup-dotnet@v4
with:
Expand Down Expand Up @@ -63,6 +69,9 @@ jobs:
steps:
- uses: actions/checkout@v3

- name: Checkout submodules
run: git submodule update --init --recursive

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
Expand Down
20 changes: 16 additions & 4 deletions Application/BocchiTracker.WPF.sln
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameCaptureRTC", "Models\Ga
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BocchiTracker.WebRTCTest", "Tests\BocchiTracker.WebRTCTest\BocchiTracker.WebRTCTest.csproj", "{B3675F7D-DF3F-4F0E-A9E0-9575381BC964}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ExternalTools", "ExternalTools", "{75B25179-1B35-461D-80AA-80EF52E7E101}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "websocket-sharp", "..\ExternalTools\websocket-sharp\websocket-sharp\websocket-sharp.csproj", "{0D0785D7-4A07-4FA0-919F-FD3AB6AED2F4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -194,14 +198,21 @@ Global
{ADEDB772-6FFB-4198-9107-1AD791899679}.Release|Any CPU.Build.0 = Release|Any CPU
{ADEDB772-6FFB-4198-9107-1AD791899679}.Release|x64.ActiveCfg = Release|Any CPU
{ADEDB772-6FFB-4198-9107-1AD791899679}.Release|x64.Build.0 = Release|Any CPU
{B3675F7D-DF3F-4F0E-A9E0-9575381BC964}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B3675F7D-DF3F-4F0E-A9E0-9575381BC964}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B3675F7D-DF3F-4F0E-A9E0-9575381BC964}.Debug|Any CPU.ActiveCfg = Debug|x64
{B3675F7D-DF3F-4F0E-A9E0-9575381BC964}.Debug|Any CPU.Build.0 = Debug|x64
{B3675F7D-DF3F-4F0E-A9E0-9575381BC964}.Debug|x64.ActiveCfg = Debug|x64
{B3675F7D-DF3F-4F0E-A9E0-9575381BC964}.Debug|x64.Build.0 = Debug|x64
{B3675F7D-DF3F-4F0E-A9E0-9575381BC964}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B3675F7D-DF3F-4F0E-A9E0-9575381BC964}.Release|Any CPU.Build.0 = Release|Any CPU
{B3675F7D-DF3F-4F0E-A9E0-9575381BC964}.Release|Any CPU.ActiveCfg = Release|x64
{B3675F7D-DF3F-4F0E-A9E0-9575381BC964}.Release|x64.ActiveCfg = Release|x64
{B3675F7D-DF3F-4F0E-A9E0-9575381BC964}.Release|x64.Build.0 = Release|x64
{0D0785D7-4A07-4FA0-919F-FD3AB6AED2F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0D0785D7-4A07-4FA0-919F-FD3AB6AED2F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0D0785D7-4A07-4FA0-919F-FD3AB6AED2F4}.Debug|x64.ActiveCfg = Debug|Any CPU
{0D0785D7-4A07-4FA0-919F-FD3AB6AED2F4}.Debug|x64.Build.0 = Debug|Any CPU
{0D0785D7-4A07-4FA0-919F-FD3AB6AED2F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0D0785D7-4A07-4FA0-919F-FD3AB6AED2F4}.Release|Any CPU.Build.0 = Release|Any CPU
{0D0785D7-4A07-4FA0-919F-FD3AB6AED2F4}.Release|x64.ActiveCfg = Release|Any CPU
{0D0785D7-4A07-4FA0-919F-FD3AB6AED2F4}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -226,6 +237,7 @@ Global
{D214D1D6-7DBA-4F53-B070-9672BA3F7CBA} = {12AAC0C3-970D-43F6-BD47-0B662B7157F6}
{ADEDB772-6FFB-4198-9107-1AD791899679} = {677ECDC0-9125-4E30-8B8C-E0CC5F98DFF5}
{B3675F7D-DF3F-4F0E-A9E0-9575381BC964} = {E876F453-952B-4D58-AA0E-1D95DFF58FB5}
{0D0785D7-4A07-4FA0-919F-FD3AB6AED2F4} = {75B25179-1B35-461D-80AA-80EF52E7E101}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F04B3FFB-34D2-4BBE-85BA-F28DEE1BCAB6}
Expand Down
10 changes: 4 additions & 6 deletions Application/Models/Config/Configs/ProjectConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using BocchiTracker.Config.Parts;
using BocchiTracker.ServiceClientData;

namespace BocchiTracker.Config.Configs
Expand Down Expand Up @@ -49,14 +50,11 @@ public class ServiceConfig
public List<ValueMapping> DefaultValue { get; set;} = new List<ValueMapping>();
}

public class ExternalToolsPath
{
public string? ProcDumpPath { get; set; }
}

public class ProjectConfig
{
public int Port { get; set; } = 8888;
public int Port { get; set; } = 8888;

public int WebSocketPort { get; set; } = 8822;

public List<string> TicketTypes { get; set; } = new List<string> { "Bug", "Task", "Question" };

Expand Down
16 changes: 3 additions & 13 deletions Application/Models/Config/Configs/UserConfig.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using BocchiTracker.ServiceClientData;
using BocchiTracker.Config.Parts;
using BocchiTracker.ServiceClientData;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -7,20 +8,9 @@

namespace BocchiTracker.Config.Configs
{
public class UserCaptureSetting
{
public GameCaptureType GameCaptureType { get; set; } = GameCaptureType.NotUse;

public bool IncludeAudio = false;

public int RecordingFrameRate { get; set; } = 30;

public int RecordingMintes { get; set; } = 3;
}

public class UserConfig
{
public UserCaptureSetting UserCaptureSetting { get; set; } = new UserCaptureSetting();
public CaptureSetting CaptureSetting { get; set; } = new CaptureSetting();

public string? ProjectConfigFilename { get; set; }

Expand Down
21 changes: 21 additions & 0 deletions Application/Models/Config/Parts/CaptureSetting.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BocchiTracker.Config.Parts
{
public class CaptureSetting
{
public GameCaptureType GameCaptureType { get; set; } = GameCaptureType.NotUse;

public SIPSorceryMedia.Abstractions.VideoCodecsEnum VideoCodecs { get; set; } = SIPSorceryMedia.Abstractions.VideoCodecsEnum.VP8;

public bool IncludeAudio = false;

public int RecordingFrameRate { get; set; } = 30;

public int RecordingMintes { get; set; } = 3;
}
}
15 changes: 15 additions & 0 deletions Application/Models/Config/Parts/ExternalToolsPath.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BocchiTracker.Config.Parts
{
public class ExternalToolsPath
{
public string? ProcDumpPath { get; set; }

public string? FFmpegPath { get; set; }
}
}
155 changes: 133 additions & 22 deletions Application/Models/GameCaptureRTC/CaptureFrameStorage.cs
Original file line number Diff line number Diff line change
@@ -1,44 +1,155 @@

using BocchiTracker.ModelEvent;
using FFMpegCore;
using OpenCvSharp;
using Prism.Events;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using System;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace BocchiTracker.GameCaptureRTC
{
public class CaptureFrameStorage
public class CaptureFrameStorage : IDisposable
{
private int _frameRate = 30;
private int _recordingMaxFrames = 0;
public ModelEvent.CaptureStreamParameter CaptureStreamParameter { get; set; } = new ModelEvent.CaptureStreamParameter();
private object _mutext = new object();

public CaptureFrameStorage(int inFrameRate, int inRecordingMintes)
private int _maxRecordingFrameCount = 0;
private int _maxSplitFrameCount = 0;
private int _curFrameCount = 0;
private int _curSpliteFrameCount = 0;

private string _tempCancatMovieDirectory = Path.Combine(Path.GetTempPath(), "BocchiTracker", "temp", "concat_movies");
private string _tempMovieDirectory = Path.Combine(Path.GetTempPath(), "BocchiTracker", "temp", "movies");
private string _tempPicsDirectory = Path.Combine(Path.GetTempPath(), "BocchiTracker", "temp", "pics");

private int _movieID = 0;
private int _adjustedwidth = 640;
private int _adjustedHeight = 480;

private VideoWriter _videoWriter = default!;

public CaptureFrameStorage(string inFFmpegPath, int inMaxRecordingFrameCount, int inMaxSplitFrameCount)
{
_frameRate = inFrameRate;
_recordingMaxFrames = (inRecordingMintes * 60) * _frameRate;
GlobalFFOptions.Configure(options => options.BinaryFolder = inFFmpegPath);

_maxSplitFrameCount = inMaxSplitFrameCount;
_maxRecordingFrameCount = inMaxRecordingFrameCount;

if (!Directory.Exists(_tempMovieDirectory))
Directory.CreateDirectory(_tempMovieDirectory);
if (!Directory.Exists(_tempCancatMovieDirectory))
Directory.CreateDirectory(_tempCancatMovieDirectory);
if (!Directory.Exists(_tempPicsDirectory))
Directory.CreateDirectory(_tempPicsDirectory);

Cleanup();
}

public void AddFrame(int inWidth, int inHeight, int inStride, nint inData)
{
if (CaptureStreamParameter.Frames.Count > _recordingMaxFrames)
CaptureStreamParameter.Frames.RemoveAt(0);

// メモリ領域のコピーを作成して渡す
byte[] dataCopy = new byte[inHeight * inStride];
unsafe
lock(_mutext)
{
byte* src = (byte*)inData;
for (int i = 0; i < dataCopy.Length; i++)
if(_adjustedwidth > inWidth || _adjustedwidth == 0)
_adjustedwidth = inWidth % 2 == 0 ? inWidth : inWidth - 1;
if (_adjustedHeight > inHeight || _adjustedHeight == 0)
_adjustedHeight = inHeight % 2 == 0 ? inHeight : inHeight - 1;

if (_curSpliteFrameCount == 0)
{
System.Console.WriteLine("start video capture");
if (_videoWriter == null || _videoWriter.IsDisposed)
_videoWriter = new VideoWriter();
_videoWriter.Open(Path.Combine(_tempMovieDirectory, $"movie.{_movieID}.mp4"), FourCC.MPG4, 30, new OpenCvSharp.Size(inWidth, inHeight));
++_movieID;
}

unsafe
{
byte[] dataCopy = new byte[inHeight * inStride];
unsafe
{
byte* src = (byte*)inData;
for (int i = 0; i < dataCopy.Length; i++)
{
dataCopy[i] = *(src + i);
}
}

using (var mat = new Mat(inHeight, inWidth, MatType.CV_8UC3, dataCopy, inStride))
{
_videoWriter.Write(mat);

_curFrameCount++;
_curSpliteFrameCount++;
}
}

if (_curSpliteFrameCount > _maxSplitFrameCount)
{
dataCopy[i] = *(src + i);
System.Console.WriteLine("_videoWriter wrote maximum frame, so next video...");
_curSpliteFrameCount = 0;
_videoWriter.Dispose();
}

if (_curFrameCount > _maxRecordingFrameCount)
{
var bochi_files = Directory.GetFiles(_tempMovieDirectory, "*.mp4")
.OrderBy(file => int.Parse(Regex.Match(file, @"(?<=movie\.)(\d+)(?=\.mp4)").Value))
.ToList();
if(bochi_files.Any())
{
System.Console.WriteLine("the maximum recording time has been exceeded, so remove old video file");
File.Delete(bochi_files[0]);
}
_curFrameCount -= _maxSplitFrameCount;
}
}
}

CaptureStreamParameter.Frames.Add(new ModelEvent.CaptureStreamParameter.Frame
public string ConcatMovie()
{
lock (_mutext)
{
Data = dataCopy,
Width = inWidth,
Height = inHeight,
Stride = inStride,
});
Dispose();
_curFrameCount = 0;
_curSpliteFrameCount = 0;

var output = Path.Combine(_tempCancatMovieDirectory, "bocchi_movie.mp4");
var bochi_files = Directory.GetFiles(_tempMovieDirectory, "*.mp4");
if (!bochi_files.Any())
return string.Empty;

var command = FFMpegArguments
.FromDemuxConcatInput(bochi_files)
.OutputToFile(output, overwrite: true, op => op.Resize(_adjustedwidth, _adjustedHeight));
bool ret = command.ProcessSynchronously();
if (ret)
Cleanup();
return output;
}
}

public void Cleanup()
{
var bochi_files = Directory.GetFiles(_tempMovieDirectory, "*.mp4");
foreach (var file in bochi_files)
{
File.Delete(file);
}
}

public void Dispose()
{
if (_videoWriter != null && !_videoWriter.IsDisposed)
{
_videoWriter.Dispose();
}
}
}
}
13 changes: 12 additions & 1 deletion Application/Models/GameCaptureRTC/GameCaptureRTC.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,28 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FFMpegCore" Version="5.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="obs-websocket-dotnet" Version="5.0.0.3" />
<PackageReference Include="OpenCvSharp4" Version="4.9.0.20240103" />
<PackageReference Include="OpenCvSharp4.runtime.centos7-x64" Version="4.0.0.20190129" />
<PackageReference Include="OpenCvSharp4.runtime.linux-arm" Version="4.9.0.20240103" />
<PackageReference Include="OpenCvSharp4.runtime.linux-arm64.cuda" Version="4.5.2.20210803" />
<PackageReference Include="OpenCvSharp4.runtime.osx.10.15-universal" Version="4.7.0.20230224" />
<PackageReference Include="OpenCvSharp4.runtime.osx.10.15-x64" Version="4.6.0.20230105" />
<PackageReference Include="OpenCvSharp4.runtime.ubuntu.18.04-x64" Version="4.6.0.20220608" />
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.9.0.20240103" />
<PackageReference Include="OpenCvSharp4_.runtime.ubuntu.20.04-x64" Version="4.9.0.20240103" />
<PackageReference Include="Prism.Core" Version="8.1.97" />
<PackageReference Include="SIPSorcery" Version="6.2.0" />
<PackageReference Include="SIPSorcery.WebSocketSharp" Version="0.0.1" />
<PackageReference Include="SIPSorceryMedia.Abstractions" Version="1.2.1" />
<PackageReference Include="SIPSorceryMedia.Encoders" Version="0.0.13" />
<PackageReference Include="SIPSorceryMedia.FFmpeg" Version="1.4.1" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.3" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\ExternalTools\websocket-sharp\websocket-sharp\websocket-sharp.csproj" />
<ProjectReference Include="..\Config\Config.csproj" />
<ProjectReference Include="..\ModelEvent\ModelEvent.csproj" />
</ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion Application/Models/GameCaptureRTC/Module.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace BocchiTracker.GameCaptureRTC
{
public class Module : IModule
public class GameCaptureRTCModule : IModule
{
public void OnInitialized(IContainerProvider containerProvider) {}

Expand Down
Loading

0 comments on commit 4ae1bbc

Please sign in to comment.