/*
* NatCorder
* Copyright (c) 2020 Yusuf Olokoba.
*/
namespace NatSuite.Recorders {
using UnityEngine;
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Internal;
///
/// JPG image sequence recorder.
/// This recorder is currently supported on macOS and Windows.
/// This recorder is NOT thread-safe, and as such it is not fully compliant with the `IMediaRecorder` interfacex.
///
public sealed class JPGRecorder : IMediaRecorder {
#region --Client API--
///
/// Image size.
///
public (int width, int height) frameSize => (framebuffer.width, framebuffer.height);
///
/// Create a JPG recorder.
///
/// Image width.
/// Image height.
public JPGRecorder (int imageWidth, int imageHeight) {
// Save state
this.framebuffer = new Texture2D(imageWidth, imageHeight, TextureFormat.RGBA32, false, false);
this.writeTasks = new List();
// Create directory
this.recordingPath = Utility.GetPath(string.Empty);
Directory.CreateDirectory(recordingPath);
}
///
/// Commit a video pixel buffer for encoding.
/// The pixel buffer MUST have an RGBA8888 pixel layout.
///
/// Pixel buffer containing video frame to commit.
/// Not used.
public void CommitFrame (T[] pixelBuffer, long timestamp = default) where T : struct {
var handle = GCHandle.Alloc(pixelBuffer, GCHandleType.Pinned);
CommitFrame(handle.AddrOfPinnedObject(), timestamp);
handle.Free();
}
///
/// Commit a video pixel buffer for encoding.
/// The pixel buffer MUST have an RGBA8888 pixel layout.
///
/// Pixel buffer in native memory to commit.
/// Not used.
public void CommitFrame (IntPtr nativeBuffer, long timestamp = default) {
// Encode immediately
framebuffer.LoadRawTextureData(nativeBuffer, framebuffer.width * framebuffer.height * 4);
var frameData = ImageConversion.EncodeToJPG(framebuffer);
// Write out on a worker thread
var frameIndex = ++frameCount;
writeTasks.Add(Task.Run(() => File.WriteAllBytes(Path.Combine(recordingPath, $"{frameIndex}.jpg"), frameData)));
}
///
/// This recorder does not support committing audio samples.
///
public void CommitSamples (float[] sampleBuffer = default, long timestamp = default) { }
///
/// Finish writing and return the path to the recorded media file.
///
public Task FinishWriting () {
Texture2D.Destroy(framebuffer);
return Task.WhenAll(writeTasks).ContinueWith(_ => recordingPath);
}
#endregion
#region --Operations--
private readonly Texture2D framebuffer;
private readonly string recordingPath;
private readonly List writeTasks;
private int frameCount;
#endregion
}
}