SHA256
Fix Color Space Issue
This commit is contained in:
4 files changed
+48
-30
No files matched your search
+38
-7
@@ -8,6 +8,7 @@ using ADOFAIRenderer.Data;
|
|||||||
using ADOFAIRenderer.UI;
|
using ADOFAIRenderer.UI;
|
||||||
using ADOFAIRenderer.Util;
|
using ADOFAIRenderer.Util;
|
||||||
using ADOFAIRenderer.Util.FFmpeg;
|
using ADOFAIRenderer.Util.FFmpeg;
|
||||||
|
using FFmpeg.AutoGen;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using MelonLoader;
|
using MelonLoader;
|
||||||
using MelonLoader.Utils;
|
using MelonLoader.Utils;
|
||||||
@@ -396,8 +397,25 @@ namespace ADOFAIRenderer.Core
|
|||||||
frameCountBase = Time.frameCount;
|
frameCountBase = Time.frameCount;
|
||||||
|
|
||||||
_frameReader?.Dispose();
|
_frameReader?.Dispose();
|
||||||
_frameReader = new FrameReader();
|
_frameReader = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
StartFFmpegThread();
|
StartFFmpegThread();
|
||||||
|
_frameReader = _activeVideoFFmpeg != null ? new FrameReader(_activeVideoFFmpeg.SelectedPixelFormat) : new FrameReader(AVPixelFormat.AV_PIX_FMT_YUV420P);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Melon<RenderMod>.Logger.Error($"인코더 초기화 에러: {ex}");
|
||||||
|
CommonWarningDialogUI.ShowDialog(
|
||||||
|
"인코더 오류",
|
||||||
|
$"비디오 인코더를 초기화할 수 없습니다.\n오류: {ex.Message}",
|
||||||
|
new DialogButton("확인", () =>
|
||||||
|
{
|
||||||
|
ADOBase.loader.LoadSceneWithTransition(WipeDirection.StartsFromRight, "scnEditor");
|
||||||
|
})
|
||||||
|
);
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
StartCapturing();
|
StartCapturing();
|
||||||
scrController.instance.paused = scrController.instance.audioPaused = false;
|
scrController.instance.paused = scrController.instance.audioPaused = false;
|
||||||
@@ -453,8 +471,6 @@ namespace ADOFAIRenderer.Core
|
|||||||
var fileName = startTime.ToString("yyyy-MM-dd HH-mm-ss") + ext;
|
var fileName = startTime.ToString("yyyy-MM-dd HH-mm-ss") + ext;
|
||||||
_currentOutPath = Path.Combine(MelonEnvironment.GameRootDirectory, "Render", fileName);
|
_currentOutPath = Path.Combine(MelonEnvironment.GameRootDirectory, "Render", fileName);
|
||||||
|
|
||||||
RenderThread = new Thread(() =>
|
|
||||||
{
|
|
||||||
FFmpegNativeEncoder? videoFFmpeg = null;
|
FFmpegNativeEncoder? videoFFmpeg = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -483,7 +499,25 @@ namespace ADOFAIRenderer.Core
|
|||||||
_allVideoFFmpegInstances.Add(videoFFmpeg);
|
_allVideoFFmpegInstances.Add(videoFFmpeg);
|
||||||
}
|
}
|
||||||
videoFFmpeg.Start(_currentOutPath);
|
videoFFmpeg.Start(_currentOutPath);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
if (videoFFmpeg != null)
|
||||||
|
{
|
||||||
|
lock (_allVideoFFmpegInstances)
|
||||||
|
{
|
||||||
|
_allVideoFFmpegInstances.Remove(videoFFmpeg);
|
||||||
|
}
|
||||||
|
videoFFmpeg.Dispose();
|
||||||
|
}
|
||||||
|
_activeVideoFFmpeg = null;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderThread = new Thread(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
CapturedFrame frame = default;
|
CapturedFrame frame = default;
|
||||||
@@ -565,14 +599,11 @@ namespace ADOFAIRenderer.Core
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Melon<RenderMod>.Logger.Error($"FFmpeg 렌더링 스레드 오류: {ex}");
|
Melon<RenderMod>.Logger.Error($"FFmpeg 렌더링 스레드 오류: {ex}");
|
||||||
videoFFmpeg?.Dispose();
|
videoFFmpeg.Dispose();
|
||||||
if (videoFFmpeg != null)
|
|
||||||
{
|
|
||||||
lock (_allVideoFFmpegInstances)
|
lock (_allVideoFFmpegInstances)
|
||||||
{
|
{
|
||||||
_allVideoFFmpegInstances.Remove(videoFFmpeg);
|
_allVideoFFmpegInstances.Remove(videoFFmpeg);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_activeVideoFFmpeg = null;
|
_activeVideoFFmpeg = null;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ using MelonLoader.Utils;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
|
|
||||||
[assembly: MelonInfo(typeof(RenderMod), "ADOFAI Renderer", "0.0.5-INDEV", "ADOFAI Editor Forum")]
|
[assembly: MelonInfo(typeof(RenderMod), "ADOFAI Renderer", "0.2.3-BETA", "ADOFAI Editor Forum")]
|
||||||
[assembly: MelonGame("7th Beat Games", "A Dance of Fire and Ice")]
|
[assembly: MelonGame("7th Beat Games", "A Dance of Fire and Ice")]
|
||||||
|
|
||||||
namespace ADOFAIRenderer
|
namespace ADOFAIRenderer
|
||||||
|
|||||||
@@ -158,6 +158,9 @@ namespace ADOFAIRenderer.Util.FFmpeg
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private AVPixelFormat _dstPixFmt = AVPixelFormat.AV_PIX_FMT_YUV420P;
|
private AVPixelFormat _dstPixFmt = AVPixelFormat.AV_PIX_FMT_YUV420P;
|
||||||
|
|
||||||
|
/// <summary>최종 선택되어 구동된 인코더의 픽셀 포맷입니다.</summary>
|
||||||
|
public AVPixelFormat SelectedPixelFormat => _dstPixFmt;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 인코딩된 패킷 데이터를 임시로 담을 패킷 구조체.
|
/// 인코딩된 패킷 데이터를 임시로 담을 패킷 구조체.
|
||||||
/// 매 프레임마다 할당/해제하는 오버헤드를 방지하기 위해 멤버 변수로 캐싱합니다.
|
/// 매 프레임마다 할당/해제하는 오버헤드를 방지하기 위해 멤버 변수로 캐싱합니다.
|
||||||
|
|||||||
+6
-22
@@ -3,7 +3,6 @@ using System.Buffers;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using ADOFAIRenderer.Core;
|
using ADOFAIRenderer.Core;
|
||||||
using ADOFAIRenderer.Util.FFmpeg;
|
|
||||||
using FFmpeg.AutoGen;
|
using FFmpeg.AutoGen;
|
||||||
using MelonLoader;
|
using MelonLoader;
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
@@ -27,8 +26,11 @@ namespace ADOFAIRenderer.Util
|
|||||||
private bool _isInitialized;
|
private bool _isInitialized;
|
||||||
private volatile bool _isDisposed;
|
private volatile bool _isDisposed;
|
||||||
|
|
||||||
public FrameReader()
|
private readonly AVPixelFormat _targetFormat;
|
||||||
|
|
||||||
|
public FrameReader(AVPixelFormat targetFormat)
|
||||||
{
|
{
|
||||||
|
_targetFormat = targetFormat;
|
||||||
InitializePool();
|
InitializePool();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,24 +50,6 @@ namespace ADOFAIRenderer.Util
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe AVPixelFormat PredictPixelFormat(Codec codec)
|
|
||||||
{
|
|
||||||
var candidates = GPUUtil.GetPrioritizedEncoderCandidates(codec);
|
|
||||||
// ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator
|
|
||||||
foreach (var encoderName in candidates)
|
|
||||||
{
|
|
||||||
var pCodec = ffmpeg.avcodec_find_encoder_by_name(encoderName);
|
|
||||||
if (pCodec == null) continue;
|
|
||||||
|
|
||||||
if (encoderName.Contains("qsv") || encoderName.Contains("nvenc") || encoderName.Contains("amf"))
|
|
||||||
{
|
|
||||||
return AVPixelFormat.AV_PIX_FMT_NV12;
|
|
||||||
}
|
|
||||||
return encoderName == "libvvenc" ? AVPixelFormat.AV_PIX_FMT_YUV420P10LE : AVPixelFormat.AV_PIX_FMT_YUV420P;
|
|
||||||
}
|
|
||||||
return AVPixelFormat.AV_PIX_FMT_YUV420P;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RequestFrameCapture(Texture texture, long currentFrame)
|
public void RequestFrameCapture(Texture texture, long currentFrame)
|
||||||
{
|
{
|
||||||
if (!RenderManager.IsCapturingActive) return;
|
if (!RenderManager.IsCapturingActive) return;
|
||||||
@@ -90,9 +74,9 @@ namespace ADOFAIRenderer.Util
|
|||||||
bool useGPUConversion = RenderMod.ColorConversionShader;
|
bool useGPUConversion = RenderMod.ColorConversionShader;
|
||||||
AVPixelFormat expectedFmt = AVPixelFormat.AV_PIX_FMT_RGBA;
|
AVPixelFormat expectedFmt = AVPixelFormat.AV_PIX_FMT_RGBA;
|
||||||
|
|
||||||
if (useGPUConversion && RenderManager.Instance)
|
if (useGPUConversion)
|
||||||
{
|
{
|
||||||
expectedFmt = PredictPixelFormat(RenderManager.Instance.Configuration.Codec);
|
expectedFmt = _targetFormat;
|
||||||
// Compute Shader는 NV12와 YUV420P만 지원하므로 그 외 포맷은 CPU 폴백 처리
|
// Compute Shader는 NV12와 YUV420P만 지원하므로 그 외 포맷은 CPU 폴백 처리
|
||||||
if (expectedFmt != AVPixelFormat.AV_PIX_FMT_NV12 && expectedFmt != AVPixelFormat.AV_PIX_FMT_YUV420P)
|
if (expectedFmt != AVPixelFormat.AV_PIX_FMT_NV12 && expectedFmt != AVPixelFormat.AV_PIX_FMT_YUV420P)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user