using System.Collections.Generic; using System.Threading; //----------------------------------------------------------------------------- // Copyright 2012-2021 RenderHeads Ltd. All rights reserved. //----------------------------------------------------------------------------- namespace RenderHeads.Media.AVProMovieCapture { /// Allows the user to monitor a capture that has completed, but the file is still being written to asynchronously public class FileWritingHandler : System.IDisposable { private string _path; private int _handle; private bool _deleteFile; private OutputTarget _outputTarget; private VideoEncoderHints _videoEncodingHints; private ManualResetEvent _postProcessEvent; public string Path { get { return _path; } } internal FileWritingHandler(OutputTarget outputTarget, string path, int handle, bool deleteFile) { _outputTarget = outputTarget; _path = path; _handle = handle; _deleteFile = deleteFile; } internal void AddPostOperation(VideoEncoderHints videoEncodingHints) { _videoEncodingHints = videoEncodingHints; } private bool StartPostProcess() { UnityEngine.Debug.Assert(_postProcessEvent == null); if (_videoEncodingHints.allowFastStartStreamingPostProcess) { _postProcessEvent = MP4FileProcessing.ApplyFastStartAsync(_path, false); if (_postProcessEvent == null) { UnityEngine.Debug.LogWarning("[AVProMovieCapture] failed moving atom 'moov' to start of file for fast streaming"); } } return true; } public bool IsFileReady() { bool result = true; if (_handle >= 0) { result = NativePlugin.IsFileWritingComplete(_handle); if (result) { if (_videoEncodingHints != null) { result = StartPostProcess(); _videoEncodingHints = null; } if (_postProcessEvent != null) { result = _postProcessEvent.WaitOne(1); } if (result) { Dispose(); } } } return result; } public void Dispose() { if (_handle >= 0) { NativePlugin.FreeRecorder(_handle); _handle = -1; // Issue the free resources plugin event NativePlugin.RenderThreadEvent(NativePlugin.PluginEvent.FreeResources, -1); if (_deleteFile) { CaptureBase.DeleteCapture(_outputTarget, _path); } } _videoEncodingHints = null; _postProcessEvent = null; } // Helper method for cleaning up a list // TODO: add an optional System.Action callback for each time the file writer completes public static bool Cleanup(List list) { bool anyRemoved = false; // NOTE: We iterate in reverse order as we're removing elements from the list for (int i = list.Count - 1; i >= 0; i--) { FileWritingHandler handler = list[i]; if (handler.IsFileReady()) { list.RemoveAt(i); anyRemoved = true; } } return anyRemoved; } } }