150 lines
3.2 KiB
C#
150 lines
3.2 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Windows.Forms;
|
|
|
|
using BizHawk.Emulation.Common;
|
|
|
|
namespace BizHawk.Client.EmuHawk
|
|
{
|
|
/// <summary>
|
|
/// dumps in the "nut" container format
|
|
/// uncompressed video and audio
|
|
/// </summary>
|
|
[VideoWriter("nut", "NUT writer", "Writes a series of .nut files to disk, a container format which can be opened by ffmpeg. All data is uncompressed. Splits occur on resolution changes. NOT RECOMMENDED FOR USE.")]
|
|
public class NutWriter : IVideoWriter
|
|
{
|
|
/// <summary>
|
|
/// dummy codec token class
|
|
/// </summary>
|
|
private class NutWriterToken : IDisposable
|
|
{
|
|
public void Dispose()
|
|
{
|
|
}
|
|
}
|
|
|
|
public void SetFrame(int frame) { }
|
|
|
|
public void SetVideoCodecToken(IDisposable token)
|
|
{
|
|
// ignored
|
|
}
|
|
public IDisposable AcquireVideoCodecToken(IWin32Window hwnd)
|
|
{
|
|
return new NutWriterToken();
|
|
}
|
|
|
|
|
|
// avParams
|
|
private int _fpsNum, _fpsDen, _width, _height, _sampleRate, _channels;
|
|
|
|
private NutMuxer _current;
|
|
private string _baseName;
|
|
private int _segment;
|
|
|
|
public void OpenFile(string baseName)
|
|
{
|
|
_baseName = Path.Combine(
|
|
Path.GetDirectoryName(baseName) ?? "",
|
|
Path.GetFileNameWithoutExtension(baseName) ?? "");
|
|
_segment = 0;
|
|
|
|
StartSegment();
|
|
}
|
|
|
|
private void StartSegment()
|
|
{
|
|
var currentFile = File.Open($"{_baseName}_{_segment,4:D4}.nut", FileMode.Create, FileAccess.Write);
|
|
_current = new NutMuxer(_width, _height, _fpsNum, _fpsDen, _sampleRate, _channels, currentFile);
|
|
}
|
|
|
|
private void EndSegment()
|
|
{
|
|
_current.Finish();
|
|
_current = null;
|
|
}
|
|
|
|
public void CloseFile()
|
|
{
|
|
EndSegment();
|
|
}
|
|
|
|
public void AddFrame(IVideoProvider source)
|
|
{
|
|
if (source.BufferHeight != _height || source.BufferWidth != _width)
|
|
{
|
|
SetVideoParameters(source.BufferWidth, source.BufferHeight);
|
|
}
|
|
|
|
_current.WriteVideoFrame(source.GetVideoBuffer());
|
|
}
|
|
|
|
public void AddSamples(short[] samples)
|
|
{
|
|
_current.WriteAudioFrame(samples);
|
|
}
|
|
|
|
public void SetMovieParameters(int fpsNum, int fpsDen)
|
|
{
|
|
_fpsNum = fpsNum;
|
|
_fpsDen = fpsDen;
|
|
if (_current != null)
|
|
{
|
|
EndSegment();
|
|
_segment++;
|
|
StartSegment();
|
|
}
|
|
}
|
|
|
|
public void SetVideoParameters(int width, int height)
|
|
{
|
|
_width = width;
|
|
_height = height;
|
|
if (_current != null)
|
|
{
|
|
EndSegment();
|
|
_segment++;
|
|
StartSegment();
|
|
}
|
|
}
|
|
|
|
/// <exception cref="ArgumentOutOfRangeException"><paramref name="bits"/> is not <c>16</c></exception>
|
|
public void SetAudioParameters(int sampleRate, int channels, int bits)
|
|
{
|
|
if (bits != 16)
|
|
{
|
|
throw new ArgumentOutOfRangeException(nameof(bits), "Audio depth must be 16 bit!");
|
|
}
|
|
|
|
_sampleRate = sampleRate;
|
|
_channels = channels;
|
|
}
|
|
|
|
public void SetMetaData(string gameName, string authors, ulong lengthMs, ulong rerecords)
|
|
{
|
|
// could be implemented?
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (_current != null)
|
|
{
|
|
EndSegment();
|
|
}
|
|
|
|
_baseName = null;
|
|
}
|
|
|
|
public string DesiredExtension() => "nut";
|
|
|
|
public void SetDefaultVideoCodecToken()
|
|
{
|
|
// ignored
|
|
}
|
|
|
|
public bool UsesAudio => true;
|
|
|
|
public bool UsesVideo => true;
|
|
}
|
|
}
|