fix AviWriter
This commit is contained in:
parent
b5ef422ab6
commit
93562b86e7
|
@ -6,11 +6,11 @@ namespace Windows.Win32
|
||||||
public static partial class Win32Imports
|
public static partial class Win32Imports
|
||||||
{
|
{
|
||||||
/// <seealso cref="AVISaveOptions(HWND, uint, int, IAVIStream[], AVICOMPRESSOPTIONS**)"/>
|
/// <seealso cref="AVISaveOptions(HWND, uint, int, IAVIStream[], AVICOMPRESSOPTIONS**)"/>
|
||||||
public static unsafe nint AVISaveOptions(IAVIStream[] ppavi, ref AVICOMPRESSOPTIONS opts, HWND owner)
|
public static unsafe nint AVISaveOptions(IAVIStream ppavi, ref AVICOMPRESSOPTIONS opts, HWND owner)
|
||||||
{
|
{
|
||||||
fixed (AVICOMPRESSOPTIONS* popts = &opts)
|
fixed (AVICOMPRESSOPTIONS* popts = &opts)
|
||||||
{
|
{
|
||||||
return AVISaveOptions(owner, uiFlags: 0, nStreams: 1, ppavi, &popts);
|
return AVISaveOptions(owner, uiFlags: 0, nStreams: 1, [ ppavi ], &popts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,8 @@ namespace Windows.Win32
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <seealso cref="HeapAlloc(SafeHandle, HEAP_FLAGS, nuint)"/>
|
/// <seealso cref="HeapAlloc(SafeHandle, HEAP_FLAGS, nuint)"/>
|
||||||
public static unsafe IntPtr HeapAlloc(int dwBytes, HEAP_FLAGS dwFlags = HEAP_FLAGS.HEAP_NONE)
|
public static unsafe void* HeapAlloc(int dwBytes, HEAP_FLAGS dwFlags = HEAP_FLAGS.HEAP_NONE)
|
||||||
=> unchecked((IntPtr) HeapAlloc(GetProcessHeap_SafeHandle(), dwFlags, dwBytes: (UIntPtr) dwBytes));
|
=> HeapAlloc(GetProcessHeap_SafeHandle(), dwFlags, dwBytes: (UIntPtr) dwBytes);
|
||||||
|
|
||||||
/// <inheritdoc cref="IsWow64Process(HANDLE, BOOL*)"/>
|
/// <inheritdoc cref="IsWow64Process(HANDLE, BOOL*)"/>
|
||||||
public static unsafe BOOL IsWow64Process(HANDLE hProcess, out BOOL Wow64Process)
|
public static unsafe BOOL IsWow64Process(HANDLE hProcess, out BOOL Wow64Process)
|
||||||
|
|
|
@ -7,11 +7,9 @@ using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
using BizHawk.Client.Common;
|
using BizHawk.Client.Common;
|
||||||
using BizHawk.Common;
|
|
||||||
using BizHawk.Common.PathExtensions;
|
using BizHawk.Common.PathExtensions;
|
||||||
using BizHawk.Emulation.Common;
|
using BizHawk.Emulation.Common;
|
||||||
|
|
||||||
using Windows.Win32;
|
|
||||||
using Windows.Win32.Graphics.Gdi;
|
using Windows.Win32.Graphics.Gdi;
|
||||||
using Windows.Win32.Media.Audio;
|
using Windows.Win32.Media.Audio;
|
||||||
using Windows.Win32.Media.Multimedia;
|
using Windows.Win32.Media.Multimedia;
|
||||||
|
@ -351,7 +349,8 @@ namespace BizHawk.Client.EmuHawk
|
||||||
wfex.nAvgBytesPerSec = (uint)(wfex.nBlockAlign * a_samplerate);
|
wfex.nAvgBytesPerSec = (uint)(wfex.nBlockAlign * a_samplerate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int fps, fps_scale;
|
public uint fps;
|
||||||
|
public uint fps_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Parameters _parameters = new Parameters();
|
private readonly Parameters _parameters = new Parameters();
|
||||||
|
@ -365,10 +364,10 @@ namespace BizHawk.Client.EmuHawk
|
||||||
bool change = false;
|
bool change = false;
|
||||||
|
|
||||||
change |= fpsNum != _parameters.fps;
|
change |= fpsNum != _parameters.fps;
|
||||||
_parameters.fps = fpsNum;
|
_parameters.fps = (uint)fpsNum;
|
||||||
|
|
||||||
change |= _parameters.fps_scale != fpsDen;
|
change |= _parameters.fps_scale != fpsDen;
|
||||||
_parameters.fps_scale = fpsDen;
|
_parameters.fps_scale = (uint)fpsDen;
|
||||||
|
|
||||||
if (change)
|
if (change)
|
||||||
{
|
{
|
||||||
|
@ -418,7 +417,7 @@ namespace BizHawk.Client.EmuHawk
|
||||||
public byte[] Format = Array.Empty<byte>();
|
public byte[] Format = Array.Empty<byte>();
|
||||||
public byte[] Parms = Array.Empty<byte>();
|
public byte[] Parms = Array.Empty<byte>();
|
||||||
|
|
||||||
private static unsafe string Decode_mmioFOURCC(int code)
|
private static string Decode_mmioFOURCC(uint code)
|
||||||
{
|
{
|
||||||
var chs = stackalloc char[4];
|
var chs = stackalloc char[4];
|
||||||
|
|
||||||
|
@ -437,19 +436,19 @@ namespace BizHawk.Client.EmuHawk
|
||||||
var ret = new CodecToken
|
var ret = new CodecToken
|
||||||
{
|
{
|
||||||
_comprOptions = opts,
|
_comprOptions = opts,
|
||||||
codec = unchecked((int) Decode_mmioFOURCC(opts.fccHandler)),
|
codec = Decode_mmioFOURCC(opts.fccHandler),
|
||||||
Format = new byte[opts.cbFormat],
|
Format = new byte[opts.cbFormat],
|
||||||
Parms = new byte[opts.cbParms],
|
Parms = new byte[opts.cbParms],
|
||||||
};
|
};
|
||||||
|
|
||||||
if (opts.lpFormat is not null)
|
if (opts.lpFormat is not null)
|
||||||
{
|
{
|
||||||
Marshal.Copy(opts.lpFormat, ret.Format, 0, opts.cbFormat);
|
Marshal.Copy((IntPtr)opts.lpFormat, ret.Format, 0, unchecked((int)opts.cbFormat));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.lpParms is not null)
|
if (opts.lpParms is not null)
|
||||||
{
|
{
|
||||||
Marshal.Copy(opts.lpParms, ret.Parms, 0, opts.cbParms);
|
Marshal.Copy((IntPtr)opts.lpParms, ret.Parms, 0, unchecked((int)opts.cbParms));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -478,14 +477,14 @@ namespace BizHawk.Client.EmuHawk
|
||||||
{
|
{
|
||||||
if (_comprOptions.cbParms != 0)
|
if (_comprOptions.cbParms != 0)
|
||||||
{
|
{
|
||||||
_comprOptions.lpParms = Win32Imports.HeapAlloc(_comprOptions.cbParms);
|
_comprOptions.lpParms = AVIWriterImports.HeapAlloc(unchecked((int)_comprOptions.cbParms));
|
||||||
Marshal.Copy(Parms, 0, _comprOptions.lpParms, _comprOptions.cbParms);
|
Marshal.Copy(Parms, 0, (IntPtr)_comprOptions.lpParms, unchecked((int)_comprOptions.cbParms));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_comprOptions.cbFormat != 0)
|
if (_comprOptions.cbFormat != 0)
|
||||||
{
|
{
|
||||||
_comprOptions.lpFormat = Win32Imports.HeapAlloc(_comprOptions.cbFormat);
|
_comprOptions.lpFormat = AVIWriterImports.HeapAlloc(unchecked((int)_comprOptions.cbFormat));
|
||||||
Marshal.Copy(Format, 0, _comprOptions.lpFormat, _comprOptions.cbFormat);
|
Marshal.Copy(Format, 0, (IntPtr)_comprOptions.lpFormat, unchecked((int)_comprOptions.cbFormat));
|
||||||
}
|
}
|
||||||
|
|
||||||
opts = _comprOptions;
|
opts = _comprOptions;
|
||||||
|
@ -538,8 +537,8 @@ namespace BizHawk.Client.EmuHawk
|
||||||
comprOptions.cbParms = b.ReadUInt32();
|
comprOptions.cbParms = b.ReadUInt32();
|
||||||
comprOptions.dwInterleaveEvery = b.ReadUInt32();
|
comprOptions.dwInterleaveEvery = b.ReadUInt32();
|
||||||
|
|
||||||
format = b.ReadBytes(comprOptions.cbFormat);
|
format = b.ReadBytes(unchecked((int)comprOptions.cbFormat));
|
||||||
parms = b.ReadBytes(comprOptions.cbParms);
|
parms = b.ReadBytes(unchecked((int)comprOptions.cbParms));
|
||||||
}
|
}
|
||||||
catch (IOException)
|
catch (IOException)
|
||||||
{
|
{
|
||||||
|
@ -579,7 +578,7 @@ namespace BizHawk.Client.EmuHawk
|
||||||
{
|
{
|
||||||
static AviWriterSegment()
|
static AviWriterSegment()
|
||||||
{
|
{
|
||||||
AVIWriterImports.AVIFileInit();
|
MemoryApiImports.AVIFileInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -587,7 +586,10 @@ namespace BizHawk.Client.EmuHawk
|
||||||
|
|
||||||
private CodecToken _currVideoCodecToken;
|
private CodecToken _currVideoCodecToken;
|
||||||
private bool _isOpen;
|
private bool _isOpen;
|
||||||
private IntPtr _pAviFile, _pAviRawVideoStream, _pAviRawAudioStream, _pAviCompressedVideoStream;
|
private IAVIFile _pAviFile;
|
||||||
|
private IAVIStream _pAviRawVideoStream;
|
||||||
|
private IAVIStream _pAviRawAudioStream;
|
||||||
|
private IAVIStream _pAviCompressedVideoStream;
|
||||||
private IntPtr _pGlobalBuf;
|
private IntPtr _pGlobalBuf;
|
||||||
private int _pGlobalBuffSize;
|
private int _pGlobalBuffSize;
|
||||||
|
|
||||||
|
@ -629,15 +631,15 @@ namespace BizHawk.Client.EmuHawk
|
||||||
public long GetLengthApproximation()
|
public long GetLengthApproximation()
|
||||||
=> _outStatus.video_bytes + _outStatus.audio_bytes;
|
=> _outStatus.video_bytes + _outStatus.audio_bytes;
|
||||||
|
|
||||||
public static unsafe int AVISaveOptions(IntPtr stream, ref AVICOMPRESSOPTIONS opts, IntPtr owner)
|
public static int AVISaveOptions(IAVIStream stream, ref AVICOMPRESSOPTIONS opts, IntPtr owner)
|
||||||
=> unchecked((int) AVIWriterImports.AVISaveOptions((IAVIStream[]) (void*) stream, ref opts, new(owner)));
|
=> unchecked((int) AVIWriterImports.AVISaveOptions(stream, ref opts, new(owner)));
|
||||||
|
|
||||||
private Parameters _parameters;
|
private Parameters _parameters;
|
||||||
|
|
||||||
/// <exception cref="InvalidOperationException">unmanaged call failed</exception>
|
/// <exception cref="InvalidOperationException">unmanaged call failed</exception>
|
||||||
public void OpenFile(string destPath, Parameters parameters, CodecToken videoCodecToken)
|
public void OpenFile(string destPath, Parameters parameters, CodecToken videoCodecToken)
|
||||||
{
|
{
|
||||||
static int mmioFOURCC(string str) => (
|
static uint mmioFOURCC(string str) => (uint)(
|
||||||
(byte)str[0] |
|
(byte)str[0] |
|
||||||
((byte)str[1] << 8) |
|
((byte)str[1] << 8) |
|
||||||
((byte)str[2] << 16) |
|
((byte)str[2] << 16) |
|
||||||
|
@ -656,10 +658,10 @@ namespace BizHawk.Client.EmuHawk
|
||||||
}
|
}
|
||||||
|
|
||||||
var hr = AVIWriterImports.AVIFileOpenW(
|
var hr = AVIWriterImports.AVIFileOpenW(
|
||||||
ref _pAviFile,
|
out _pAviFile,
|
||||||
destPath,
|
destPath,
|
||||||
AVIWriterImports.OpenFileStyle.OF_CREATE | AVIWriterImports.OpenFileStyle.OF_WRITE,
|
(uint)(BizHawk.Common.AVIWriterImports.OpenFileStyle.OF_CREATE | BizHawk.Common.AVIWriterImports.OpenFileStyle.OF_WRITE),
|
||||||
0);
|
null);
|
||||||
var hrEx = Marshal.GetExceptionForHR(hr);
|
var hrEx = Marshal.GetExceptionForHR(hr);
|
||||||
if (hrEx != null)
|
if (hrEx != null)
|
||||||
{
|
{
|
||||||
|
@ -673,12 +675,12 @@ namespace BizHawk.Client.EmuHawk
|
||||||
vidstream_header.fccType = mmioFOURCC("vids");
|
vidstream_header.fccType = mmioFOURCC("vids");
|
||||||
vidstream_header.dwRate = parameters.fps;
|
vidstream_header.dwRate = parameters.fps;
|
||||||
vidstream_header.dwScale = parameters.fps_scale;
|
vidstream_header.dwScale = parameters.fps_scale;
|
||||||
vidstream_header.dwSuggestedBufferSize = (int)bmih.biSizeImage;
|
vidstream_header.dwSuggestedBufferSize = bmih.biSizeImage;
|
||||||
|
|
||||||
hr = AVIWriterImports.AVIFileCreateStreamW(
|
hr = AVIWriterImports.AVIFileCreateStreamW(
|
||||||
_pAviFile,
|
_pAviFile,
|
||||||
out _pAviRawVideoStream,
|
out _pAviRawVideoStream,
|
||||||
ref vidstream_header);
|
in vidstream_header);
|
||||||
hrEx = Marshal.GetExceptionForHR(hr);
|
hrEx = Marshal.GetExceptionForHR(hr);
|
||||||
if (hrEx != null)
|
if (hrEx != null)
|
||||||
{
|
{
|
||||||
|
@ -691,9 +693,9 @@ namespace BizHawk.Client.EmuHawk
|
||||||
WAVEFORMATEX wfex = default;
|
WAVEFORMATEX wfex = default;
|
||||||
parameters.PopulateWAVEFORMATEX(ref wfex);
|
parameters.PopulateWAVEFORMATEX(ref wfex);
|
||||||
audstream_header.fccType = mmioFOURCC("auds");
|
audstream_header.fccType = mmioFOURCC("auds");
|
||||||
audstream_header.dwQuality = -1;
|
audstream_header.dwQuality = unchecked((uint)-1);
|
||||||
audstream_header.dwScale = wfex.nBlockAlign;
|
audstream_header.dwScale = wfex.nBlockAlign;
|
||||||
audstream_header.dwRate = (int)wfex.nAvgBytesPerSec;
|
audstream_header.dwRate = wfex.nAvgBytesPerSec;
|
||||||
audstream_header.dwSampleSize = wfex.nBlockAlign;
|
audstream_header.dwSampleSize = wfex.nBlockAlign;
|
||||||
audstream_header.dwInitialFrames = 1; // ??? optimal value?
|
audstream_header.dwInitialFrames = 1; // ??? optimal value?
|
||||||
|
|
||||||
|
@ -761,8 +763,8 @@ namespace BizHawk.Client.EmuHawk
|
||||||
var hr = AVIWriterImports.AVIMakeCompressedStream(
|
var hr = AVIWriterImports.AVIMakeCompressedStream(
|
||||||
out _pAviCompressedVideoStream,
|
out _pAviCompressedVideoStream,
|
||||||
_pAviRawVideoStream,
|
_pAviRawVideoStream,
|
||||||
ref opts,
|
in opts,
|
||||||
IntPtr.Zero);
|
null);
|
||||||
var hrEx = Marshal.GetExceptionForHR(hr);
|
var hrEx = Marshal.GetExceptionForHR(hr);
|
||||||
CodecToken.DeallocateAVICOMPRESSOPTIONS(ref opts);
|
CodecToken.DeallocateAVICOMPRESSOPTIONS(ref opts);
|
||||||
if (hrEx != null)
|
if (hrEx != null)
|
||||||
|
@ -785,7 +787,7 @@ namespace BizHawk.Client.EmuHawk
|
||||||
hr = AVIWriterImports.AVIStreamSetFormat(
|
hr = AVIWriterImports.AVIStreamSetFormat(
|
||||||
_pAviCompressedVideoStream,
|
_pAviCompressedVideoStream,
|
||||||
0,
|
0,
|
||||||
ref bmih,
|
&bmih,
|
||||||
Marshal.SizeOf(bmih));
|
Marshal.SizeOf(bmih));
|
||||||
hrEx = Marshal.GetExceptionForHR(hr);
|
hrEx = Marshal.GetExceptionForHR(hr);
|
||||||
if (hrEx != null)
|
if (hrEx != null)
|
||||||
|
@ -802,7 +804,7 @@ namespace BizHawk.Client.EmuHawk
|
||||||
hr = AVIWriterImports.AVIStreamSetFormat(
|
hr = AVIWriterImports.AVIStreamSetFormat(
|
||||||
_pAviRawAudioStream,
|
_pAviRawAudioStream,
|
||||||
0,
|
0,
|
||||||
ref wfex,
|
&wfex,
|
||||||
Marshal.SizeOf(wfex));
|
Marshal.SizeOf(wfex));
|
||||||
hrEx = Marshal.GetExceptionForHR(hr);
|
hrEx = Marshal.GetExceptionForHR(hr);
|
||||||
if (hrEx != null)
|
if (hrEx != null)
|
||||||
|
@ -818,22 +820,22 @@ namespace BizHawk.Client.EmuHawk
|
||||||
public void CloseFile()
|
public void CloseFile()
|
||||||
{
|
{
|
||||||
CloseStreams();
|
CloseStreams();
|
||||||
if (_pAviRawAudioStream != IntPtr.Zero)
|
if (_pAviRawAudioStream is not null)
|
||||||
{
|
{
|
||||||
_ = AVIWriterImports.AVIStreamRelease(_pAviRawAudioStream);
|
_ = AVIWriterImports.AVIStreamRelease(_pAviRawAudioStream);
|
||||||
_pAviRawAudioStream = IntPtr.Zero;
|
_pAviRawAudioStream = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pAviRawVideoStream != IntPtr.Zero)
|
if (_pAviRawVideoStream is not null)
|
||||||
{
|
{
|
||||||
_ = AVIWriterImports.AVIStreamRelease(_pAviRawVideoStream);
|
_ = AVIWriterImports.AVIStreamRelease(_pAviRawVideoStream);
|
||||||
_pAviRawVideoStream = IntPtr.Zero;
|
_pAviRawVideoStream = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pAviFile != IntPtr.Zero)
|
if (_pAviFile is not null)
|
||||||
{
|
{
|
||||||
_ = AVIWriterImports.AVIFileRelease(_pAviFile);
|
_ = AVIWriterImports.AVIFileRelease(_pAviFile);
|
||||||
_pAviFile = IntPtr.Zero;
|
_pAviFile = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pGlobalBuf != IntPtr.Zero)
|
if (_pGlobalBuf != IntPtr.Zero)
|
||||||
|
@ -849,15 +851,15 @@ namespace BizHawk.Client.EmuHawk
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void CloseStreams()
|
private void CloseStreams()
|
||||||
{
|
{
|
||||||
if (_pAviRawAudioStream != IntPtr.Zero)
|
if (_pAviRawAudioStream is not null)
|
||||||
{
|
{
|
||||||
FlushBufferedAudio();
|
FlushBufferedAudio();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pAviCompressedVideoStream != IntPtr.Zero)
|
if (_pAviCompressedVideoStream is not null)
|
||||||
{
|
{
|
||||||
_ = AVIWriterImports.AVIStreamRelease(_pAviCompressedVideoStream);
|
_ = AVIWriterImports.AVIStreamRelease(_pAviCompressedVideoStream);
|
||||||
_pAviCompressedVideoStream = IntPtr.Zero;
|
_pAviCompressedVideoStream = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -885,7 +887,7 @@ namespace BizHawk.Client.EmuHawk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe void FlushBufferedAudio()
|
private void FlushBufferedAudio()
|
||||||
{
|
{
|
||||||
var todo = _outStatus.audio_buffered_shorts;
|
var todo = _outStatus.audio_buffered_shorts;
|
||||||
var todo_realsamples = todo / 2;
|
var todo_realsamples = todo / 2;
|
||||||
|
@ -898,22 +900,23 @@ namespace BizHawk.Client.EmuHawk
|
||||||
}
|
}
|
||||||
|
|
||||||
// (TODO - inefficient- build directly in a buffer)
|
// (TODO - inefficient- build directly in a buffer)
|
||||||
|
int bytesWritten;
|
||||||
_ = AVIWriterImports.AVIStreamWrite(
|
_ = AVIWriterImports.AVIStreamWrite(
|
||||||
_pAviRawAudioStream,
|
_pAviRawAudioStream,
|
||||||
_outStatus.audio_samples,
|
_outStatus.audio_samples,
|
||||||
todo_realsamples,
|
todo_realsamples,
|
||||||
buf,
|
buf.ToPointer(),
|
||||||
todo_realsamples * 4,
|
todo_realsamples * 4,
|
||||||
0,
|
0,
|
||||||
IntPtr.Zero,
|
null,
|
||||||
out var bytes_written);
|
&bytesWritten);
|
||||||
_outStatus.audio_samples += todo_realsamples;
|
_outStatus.audio_samples += todo_realsamples;
|
||||||
_outStatus.audio_bytes += bytes_written;
|
_outStatus.audio_bytes += bytesWritten;
|
||||||
_outStatus.audio_buffered_shorts = 0;
|
_outStatus.audio_buffered_shorts = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <exception cref="InvalidOperationException">attempted frame resize during encoding</exception>
|
/// <exception cref="InvalidOperationException">attempted frame resize during encoding</exception>
|
||||||
public unsafe void AddFrame(IVideoProvider source)
|
public void AddFrame(IVideoProvider source)
|
||||||
{
|
{
|
||||||
if (_parameters.width != source.BufferWidth
|
if (_parameters.width != source.BufferWidth
|
||||||
|| _parameters.height != source.BufferHeight)
|
|| _parameters.height != source.BufferHeight)
|
||||||
|
@ -953,17 +956,17 @@ namespace BizHawk.Client.EmuHawk
|
||||||
bp += pitch_add;
|
bp += pitch_add;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bytes_written = default;
|
int bytesWritten;
|
||||||
_ = AVIWriterImports.AVIStreamWrite(
|
_ = AVIWriterImports.AVIStreamWrite(
|
||||||
_pAviCompressedVideoStream,
|
_pAviCompressedVideoStream,
|
||||||
lStart: _outStatus.video_frames,
|
lStart: _outStatus.video_frames,
|
||||||
samples: 1,
|
lSamples: 1,
|
||||||
lpBuffer: bytes_ptr,
|
lpBuffer: bytes_ptr,
|
||||||
cbBuffer: todo,
|
cbBuffer: todo,
|
||||||
dwFlags: AVIWriterImports.AVIIF_KEYFRAME,
|
dwFlags: AVIWriterImports.AVIIF_KEYFRAME,
|
||||||
plSampWritten: default,
|
plSampWritten: null,
|
||||||
plBytesWritten: &bytes_written);
|
plBytesWritten: &bytesWritten);
|
||||||
_outStatus.video_bytes += bytes_written;
|
_outStatus.video_bytes += bytesWritten;
|
||||||
_outStatus.video_frames++;
|
_outStatus.video_frames++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -994,16 +997,17 @@ namespace BizHawk.Client.EmuHawk
|
||||||
idx -= w * 2;
|
idx -= w * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bytesWritten;
|
||||||
_ = AVIWriterImports.AVIStreamWrite(
|
_ = AVIWriterImports.AVIStreamWrite(
|
||||||
_pAviCompressedVideoStream,
|
_pAviCompressedVideoStream,
|
||||||
lStart: _outStatus.video_frames,
|
lStart: _outStatus.video_frames,
|
||||||
samples: 1,
|
lSamples: 1,
|
||||||
lpBuffer: bytes_ptr,
|
lpBuffer: bytes_ptr,
|
||||||
cbBuffer: todo * 3,
|
cbBuffer: todo * 3,
|
||||||
dwFlags: AVIWriterImports.AVIIF_KEYFRAME,
|
dwFlags: AVIWriterImports.AVIIF_KEYFRAME,
|
||||||
plSampWritten: default,
|
plSampWritten: null,
|
||||||
plBytesWritten: &bytes_written);
|
plBytesWritten: &bytesWritten);
|
||||||
_outStatus.video_bytes += bytes_written;
|
_outStatus.video_bytes += bytesWritten;
|
||||||
_outStatus.video_frames++;
|
_outStatus.video_frames++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
#if AVI_SUPPORT
|
#if AVI_SUPPORT
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
// ReSharper disable FieldCanBeMadeReadOnly.Global
|
|
||||||
|
|
||||||
namespace BizHawk.Common
|
namespace BizHawk.Common
|
||||||
{
|
{
|
||||||
|
@ -15,89 +12,6 @@ namespace BizHawk.Common
|
||||||
OF_WRITE = 0x00000001,
|
OF_WRITE = 0x00000001,
|
||||||
OF_CREATE = 0x00001000,
|
OF_CREATE = 0x00001000,
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
||||||
public struct AVISTREAMINFOW
|
|
||||||
{
|
|
||||||
public int fccType;
|
|
||||||
public int fccHandler;
|
|
||||||
public int dwFlags;
|
|
||||||
public int dwCaps;
|
|
||||||
public short wPriority;
|
|
||||||
public short wLanguage;
|
|
||||||
public int dwScale;
|
|
||||||
public int dwRate;
|
|
||||||
public int dwStart;
|
|
||||||
public int dwLength;
|
|
||||||
public int dwInitialFrames;
|
|
||||||
public int dwSuggestedBufferSize;
|
|
||||||
public int dwQuality;
|
|
||||||
public int dwSampleSize;
|
|
||||||
public RECT rcFrame;
|
|
||||||
public int dwEditCount;
|
|
||||||
public int dwFormatChangeCount;
|
|
||||||
[MarshalAs(UnmanagedType.LPWStr, SizeConst = 64)]
|
|
||||||
public string szName;
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
||||||
public struct RECT
|
|
||||||
{
|
|
||||||
public int Left;
|
|
||||||
public int Top;
|
|
||||||
public int Right;
|
|
||||||
public int Bottom;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
||||||
public struct BITMAPINFOHEADER
|
|
||||||
{
|
|
||||||
public uint biSize;
|
|
||||||
public int biWidth;
|
|
||||||
public int biHeight;
|
|
||||||
public ushort biPlanes;
|
|
||||||
public ushort biBitCount;
|
|
||||||
public uint biCompression;
|
|
||||||
public uint biSizeImage;
|
|
||||||
public int biXPelsPerMeter;
|
|
||||||
public int biYPelsPerMeter;
|
|
||||||
public uint biClrUsed;
|
|
||||||
public uint biClrImportant;
|
|
||||||
|
|
||||||
public void Init()
|
|
||||||
=> biSize = (uint)Marshal.SizeOf(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct AVICOMPRESSOPTIONS
|
|
||||||
{
|
|
||||||
public int fccType;
|
|
||||||
public int fccHandler;
|
|
||||||
public int dwKeyFrameEvery;
|
|
||||||
public int dwQuality;
|
|
||||||
public int dwBytesPerSecond;
|
|
||||||
public int dwFlags;
|
|
||||||
public IntPtr lpFormat;
|
|
||||||
public int cbFormat;
|
|
||||||
public IntPtr lpParms;
|
|
||||||
public int cbParms;
|
|
||||||
public int dwInterleaveEvery;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
||||||
public struct WAVEFORMATEX
|
|
||||||
{
|
|
||||||
public ushort wFormatTag;
|
|
||||||
public ushort nChannels;
|
|
||||||
public uint nSamplesPerSec;
|
|
||||||
public uint nAvgBytesPerSec;
|
|
||||||
public ushort nBlockAlign;
|
|
||||||
public ushort wBitsPerSample;
|
|
||||||
public ushort cbSize;
|
|
||||||
|
|
||||||
public void Init()
|
|
||||||
=> cbSize = (ushort)Marshal.SizeOf(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue