SHA256
Fix Incomplete Output File Handling
This commit is contained in:
2 files changed
+65
-42
No files matched your search
+41
-12
@@ -226,6 +226,11 @@ internal class RenderManager : MonoBehaviour
|
||||
private GameObject? _debugMonitorObj;
|
||||
private GameObject? _escapeHandlerObj;
|
||||
internal string? CurrentOutPath;
|
||||
|
||||
// Output file of the current render that is not finished yet.
|
||||
// Set just before the encoder opens the file, cleared by the render thread after the encoder finished the file (End).
|
||||
// Only this file is deleted when a render is cancelled, fails or the game exits (DeleteIncompleteOutputFile).
|
||||
private string? _incompleteOutputPath;
|
||||
private bool _renderSetup;
|
||||
|
||||
private void Awake()
|
||||
@@ -286,6 +291,32 @@ internal class RenderManager : MonoBehaviour
|
||||
{
|
||||
RenderThread.Join(200);
|
||||
}
|
||||
|
||||
// The encoders are disposed above, which closes the output file. An unfinished file of this render is deleted.
|
||||
DeleteIncompleteOutputFile();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the output file of the current render when the render did not finish it (_incompleteOutputPath).
|
||||
/// Files of earlier, finished renders are never deleted.
|
||||
/// Returns true when a file was deleted.
|
||||
/// </summary>
|
||||
private bool DeleteIncompleteOutputFile()
|
||||
{
|
||||
var path = Interlocked.Exchange(ref _incompleteOutputPath, null);
|
||||
if (string.IsNullOrEmpty(path) || !File.Exists(path)) return false;
|
||||
|
||||
try
|
||||
{
|
||||
File.Delete(path);
|
||||
Melon<RenderMod>.Logger.Msg($"[File Cleanup] Deleted incomplete video: {path}");
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Melon<RenderMod>.Logger.Error($"[File Cleanup] Failed to delete incomplete video: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
@@ -634,6 +665,7 @@ internal class RenderManager : MonoBehaviour
|
||||
{
|
||||
_allVideoFFmpegInstances.Add(videoFFmpeg);
|
||||
}
|
||||
Volatile.Write(ref _incompleteOutputPath, CurrentOutPath);
|
||||
videoFFmpeg.Start(CurrentOutPath);
|
||||
}
|
||||
catch (Exception)
|
||||
@@ -735,7 +767,13 @@ internal class RenderManager : MonoBehaviour
|
||||
FrameAvailableEvent.WaitOne(50);
|
||||
}
|
||||
|
||||
if (!IsRenderAborted) videoFFmpeg.End();
|
||||
if (!IsRenderAborted)
|
||||
{
|
||||
// End throws when the file cannot be finished (e.g. the trailer cannot be written),
|
||||
// which is handled as a render failure by the catch block below.
|
||||
videoFFmpeg.End();
|
||||
Volatile.Write(ref _incompleteOutputPath, null);
|
||||
}
|
||||
videoFFmpeg.Dispose();
|
||||
|
||||
lock (_allVideoFFmpegInstances)
|
||||
@@ -862,18 +900,9 @@ internal class RenderManager : MonoBehaviour
|
||||
scrController.instance.noFailInfiniteMargin = false;
|
||||
}
|
||||
|
||||
// 6. Immediately delete cancelled incomplete temporary video file
|
||||
if (!string.IsNullOrEmpty(CurrentOutPath) && File.Exists(CurrentOutPath))
|
||||
// 6. Immediately delete the incomplete video file of this render
|
||||
if (DeleteIncompleteOutputFile())
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(CurrentOutPath);
|
||||
Melon<RenderMod>.Logger.Msg($"[File Cleanup] Deleted incomplete video: {CurrentOutPath}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Melon<RenderMod>.Logger.Error($"[File Cleanup] Failed to delete temporary video: {ex.Message}");
|
||||
}
|
||||
CurrentOutPath = null;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user