Skip to content

Commit 93562b8

Browse files
committed
fix AviWriter
1 parent b5ef422 commit 93562b8

File tree

4 files changed

+63
-145
lines changed

4 files changed

+63
-145
lines changed

src/BizHawk.Bizware.Externs/AVIFIL32.dll.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ namespace Windows.Win32
66
public static partial class Win32Imports
77
{
88
/// <seealso cref="AVISaveOptions(HWND, uint, int, IAVIStream[], AVICOMPRESSOPTIONS**)"/>
9-
public static unsafe nint AVISaveOptions(IAVIStream[] ppavi, ref AVICOMPRESSOPTIONS opts, HWND owner)
9+
public static unsafe nint AVISaveOptions(IAVIStream ppavi, ref AVICOMPRESSOPTIONS opts, HWND owner)
1010
{
1111
fixed (AVICOMPRESSOPTIONS* popts = &opts)
1212
{
13-
return AVISaveOptions(owner, uiFlags: 0, nStreams: 1, ppavi, &popts);
13+
return AVISaveOptions(owner, uiFlags: 0, nStreams: 1, [ ppavi ], &popts);
1414
}
1515
}
1616
}

src/BizHawk.Bizware.Externs/KERNEL32.dll.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ public static unsafe uint GetShortPathNameW(string lpszLongPath)
1717
}
1818

1919
/// <seealso cref="HeapAlloc(SafeHandle, HEAP_FLAGS, nuint)"/>
20-
public static unsafe IntPtr HeapAlloc(int dwBytes, HEAP_FLAGS dwFlags = HEAP_FLAGS.HEAP_NONE)
21-
=> unchecked((IntPtr) HeapAlloc(GetProcessHeap_SafeHandle(), dwFlags, dwBytes: (UIntPtr) dwBytes));
20+
public static unsafe void* HeapAlloc(int dwBytes, HEAP_FLAGS dwFlags = HEAP_FLAGS.HEAP_NONE)
21+
=> HeapAlloc(GetProcessHeap_SafeHandle(), dwFlags, dwBytes: (UIntPtr) dwBytes);
2222

2323
/// <inheritdoc cref="IsWow64Process(HANDLE, BOOL*)"/>
2424
public static unsafe BOOL IsWow64Process(HANDLE hProcess, out BOOL Wow64Process)

src/BizHawk.Client.EmuHawk/AVOut/AviWriter.cs

Lines changed: 59 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@
77
using System.Threading;
88

99
using BizHawk.Client.Common;
10-
using BizHawk.Common;
1110
using BizHawk.Common.PathExtensions;
1211
using BizHawk.Emulation.Common;
1312

14-
using Windows.Win32;
1513
using Windows.Win32.Graphics.Gdi;
1614
using Windows.Win32.Media.Audio;
1715
using Windows.Win32.Media.Multimedia;
@@ -351,7 +349,8 @@ public void PopulateWAVEFORMATEX(ref WAVEFORMATEX wfex)
351349
wfex.nAvgBytesPerSec = (uint)(wfex.nBlockAlign * a_samplerate);
352350
}
353351

354-
public int fps, fps_scale;
352+
public uint fps;
353+
public uint fps_scale;
355354
}
356355

357356
private readonly Parameters _parameters = new Parameters();
@@ -365,10 +364,10 @@ public void SetMovieParameters(int fpsNum, int fpsDen)
365364
bool change = false;
366365

367366
change |= fpsNum != _parameters.fps;
368-
_parameters.fps = fpsNum;
367+
_parameters.fps = (uint)fpsNum;
369368

370369
change |= _parameters.fps_scale != fpsDen;
371-
_parameters.fps_scale = fpsDen;
370+
_parameters.fps_scale = (uint)fpsDen;
372371

373372
if (change)
374373
{
@@ -418,7 +417,7 @@ private CodecToken()
418417
public byte[] Format = Array.Empty<byte>();
419418
public byte[] Parms = Array.Empty<byte>();
420419

421-
private static unsafe string Decode_mmioFOURCC(int code)
420+
private static string Decode_mmioFOURCC(uint code)
422421
{
423422
var chs = stackalloc char[4];
424423

@@ -437,19 +436,19 @@ public static CodecToken CreateFromAVICOMPRESSOPTIONS(ref AVICOMPRESSOPTIONS opt
437436
var ret = new CodecToken
438437
{
439438
_comprOptions = opts,
440-
codec = unchecked((int) Decode_mmioFOURCC(opts.fccHandler)),
439+
codec = Decode_mmioFOURCC(opts.fccHandler),
441440
Format = new byte[opts.cbFormat],
442441
Parms = new byte[opts.cbParms],
443442
};
444443

445444
if (opts.lpFormat is not null)
446445
{
447-
Marshal.Copy(opts.lpFormat, ret.Format, 0, opts.cbFormat);
446+
Marshal.Copy((IntPtr)opts.lpFormat, ret.Format, 0, unchecked((int)opts.cbFormat));
448447
}
449448

450449
if (opts.lpParms is not null)
451450
{
452-
Marshal.Copy(opts.lpParms, ret.Parms, 0, opts.cbParms);
451+
Marshal.Copy((IntPtr)opts.lpParms, ret.Parms, 0, unchecked((int)opts.cbParms));
453452
}
454453

455454
return ret;
@@ -478,14 +477,14 @@ public void AllocateToAVICOMPRESSOPTIONS(out AVICOMPRESSOPTIONS opts)
478477
{
479478
if (_comprOptions.cbParms != 0)
480479
{
481-
_comprOptions.lpParms = Win32Imports.HeapAlloc(_comprOptions.cbParms);
482-
Marshal.Copy(Parms, 0, _comprOptions.lpParms, _comprOptions.cbParms);
480+
_comprOptions.lpParms = AVIWriterImports.HeapAlloc(unchecked((int)_comprOptions.cbParms));
481+
Marshal.Copy(Parms, 0, (IntPtr)_comprOptions.lpParms, unchecked((int)_comprOptions.cbParms));
483482
}
484483

485484
if (_comprOptions.cbFormat != 0)
486485
{
487-
_comprOptions.lpFormat = Win32Imports.HeapAlloc(_comprOptions.cbFormat);
488-
Marshal.Copy(Format, 0, _comprOptions.lpFormat, _comprOptions.cbFormat);
486+
_comprOptions.lpFormat = AVIWriterImports.HeapAlloc(unchecked((int)_comprOptions.cbFormat));
487+
Marshal.Copy(Format, 0, (IntPtr)_comprOptions.lpFormat, unchecked((int)_comprOptions.cbFormat));
489488
}
490489

491490
opts = _comprOptions;
@@ -538,8 +537,8 @@ private static CodecToken DeSerializeFromByteArray(byte[] data)
538537
comprOptions.cbParms = b.ReadUInt32();
539538
comprOptions.dwInterleaveEvery = b.ReadUInt32();
540539

541-
format = b.ReadBytes(comprOptions.cbFormat);
542-
parms = b.ReadBytes(comprOptions.cbParms);
540+
format = b.ReadBytes(unchecked((int)comprOptions.cbFormat));
541+
parms = b.ReadBytes(unchecked((int)comprOptions.cbParms));
543542
}
544543
catch (IOException)
545544
{
@@ -579,15 +578,18 @@ private class AviWriterSegment : IDisposable
579578
{
580579
static AviWriterSegment()
581580
{
582-
AVIWriterImports.AVIFileInit();
581+
MemoryApiImports.AVIFileInit();
583582
}
584583

585584
public void Dispose()
586585
=> CloseFile();
587586

588587
private CodecToken _currVideoCodecToken;
589588
private bool _isOpen;
590-
private IntPtr _pAviFile, _pAviRawVideoStream, _pAviRawAudioStream, _pAviCompressedVideoStream;
589+
private IAVIFile _pAviFile;
590+
private IAVIStream _pAviRawVideoStream;
591+
private IAVIStream _pAviRawAudioStream;
592+
private IAVIStream _pAviCompressedVideoStream;
591593
private IntPtr _pGlobalBuf;
592594
private int _pGlobalBuffSize;
593595

@@ -629,15 +631,15 @@ private class OutputStatus
629631
public long GetLengthApproximation()
630632
=> _outStatus.video_bytes + _outStatus.audio_bytes;
631633

632-
public static unsafe int AVISaveOptions(IntPtr stream, ref AVICOMPRESSOPTIONS opts, IntPtr owner)
633-
=> unchecked((int) AVIWriterImports.AVISaveOptions((IAVIStream[]) (void*) stream, ref opts, new(owner)));
634+
public static int AVISaveOptions(IAVIStream stream, ref AVICOMPRESSOPTIONS opts, IntPtr owner)
635+
=> unchecked((int) AVIWriterImports.AVISaveOptions(stream, ref opts, new(owner)));
634636

635637
private Parameters _parameters;
636638

637639
/// <exception cref="InvalidOperationException">unmanaged call failed</exception>
638640
public void OpenFile(string destPath, Parameters parameters, CodecToken videoCodecToken)
639641
{
640-
static int mmioFOURCC(string str) => (
642+
static uint mmioFOURCC(string str) => (uint)(
641643
(byte)str[0] |
642644
((byte)str[1] << 8) |
643645
((byte)str[2] << 16) |
@@ -656,10 +658,10 @@ static int mmioFOURCC(string str) => (
656658
}
657659

658660
var hr = AVIWriterImports.AVIFileOpenW(
659-
ref _pAviFile,
661+
out _pAviFile,
660662
destPath,
661-
AVIWriterImports.OpenFileStyle.OF_CREATE | AVIWriterImports.OpenFileStyle.OF_WRITE,
662-
0);
663+
(uint)(BizHawk.Common.AVIWriterImports.OpenFileStyle.OF_CREATE | BizHawk.Common.AVIWriterImports.OpenFileStyle.OF_WRITE),
664+
null);
663665
var hrEx = Marshal.GetExceptionForHR(hr);
664666
if (hrEx != null)
665667
{
@@ -673,12 +675,12 @@ static int mmioFOURCC(string str) => (
673675
vidstream_header.fccType = mmioFOURCC("vids");
674676
vidstream_header.dwRate = parameters.fps;
675677
vidstream_header.dwScale = parameters.fps_scale;
676-
vidstream_header.dwSuggestedBufferSize = (int)bmih.biSizeImage;
678+
vidstream_header.dwSuggestedBufferSize = bmih.biSizeImage;
677679

678680
hr = AVIWriterImports.AVIFileCreateStreamW(
679681
_pAviFile,
680682
out _pAviRawVideoStream,
681-
ref vidstream_header);
683+
in vidstream_header);
682684
hrEx = Marshal.GetExceptionForHR(hr);
683685
if (hrEx != null)
684686
{
@@ -691,9 +693,9 @@ static int mmioFOURCC(string str) => (
691693
WAVEFORMATEX wfex = default;
692694
parameters.PopulateWAVEFORMATEX(ref wfex);
693695
audstream_header.fccType = mmioFOURCC("auds");
694-
audstream_header.dwQuality = -1;
696+
audstream_header.dwQuality = unchecked((uint)-1);
695697
audstream_header.dwScale = wfex.nBlockAlign;
696-
audstream_header.dwRate = (int)wfex.nAvgBytesPerSec;
698+
audstream_header.dwRate = wfex.nAvgBytesPerSec;
697699
audstream_header.dwSampleSize = wfex.nBlockAlign;
698700
audstream_header.dwInitialFrames = 1; // ??? optimal value?
699701

@@ -761,8 +763,8 @@ public void OpenStreams()
761763
var hr = AVIWriterImports.AVIMakeCompressedStream(
762764
out _pAviCompressedVideoStream,
763765
_pAviRawVideoStream,
764-
ref opts,
765-
IntPtr.Zero);
766+
in opts,
767+
null);
766768
var hrEx = Marshal.GetExceptionForHR(hr);
767769
CodecToken.DeallocateAVICOMPRESSOPTIONS(ref opts);
768770
if (hrEx != null)
@@ -785,7 +787,7 @@ public void OpenStreams()
785787
hr = AVIWriterImports.AVIStreamSetFormat(
786788
_pAviCompressedVideoStream,
787789
0,
788-
ref bmih,
790+
&bmih,
789791
Marshal.SizeOf(bmih));
790792
hrEx = Marshal.GetExceptionForHR(hr);
791793
if (hrEx != null)
@@ -802,7 +804,7 @@ public void OpenStreams()
802804
hr = AVIWriterImports.AVIStreamSetFormat(
803805
_pAviRawAudioStream,
804806
0,
805-
ref wfex,
807+
&wfex,
806808
Marshal.SizeOf(wfex));
807809
hrEx = Marshal.GetExceptionForHR(hr);
808810
if (hrEx != null)
@@ -818,22 +820,22 @@ public void OpenStreams()
818820
public void CloseFile()
819821
{
820822
CloseStreams();
821-
if (_pAviRawAudioStream != IntPtr.Zero)
823+
if (_pAviRawAudioStream is not null)
822824
{
823825
_ = AVIWriterImports.AVIStreamRelease(_pAviRawAudioStream);
824-
_pAviRawAudioStream = IntPtr.Zero;
826+
_pAviRawAudioStream = null;
825827
}
826828

827-
if (_pAviRawVideoStream != IntPtr.Zero)
829+
if (_pAviRawVideoStream is not null)
828830
{
829831
_ = AVIWriterImports.AVIStreamRelease(_pAviRawVideoStream);
830-
_pAviRawVideoStream = IntPtr.Zero;
832+
_pAviRawVideoStream = null;
831833
}
832834

833-
if (_pAviFile != IntPtr.Zero)
835+
if (_pAviFile is not null)
834836
{
835837
_ = AVIWriterImports.AVIFileRelease(_pAviFile);
836-
_pAviFile = IntPtr.Zero;
838+
_pAviFile = null;
837839
}
838840

839841
if (_pGlobalBuf != IntPtr.Zero)
@@ -849,15 +851,15 @@ public void CloseFile()
849851
/// </summary>
850852
private void CloseStreams()
851853
{
852-
if (_pAviRawAudioStream != IntPtr.Zero)
854+
if (_pAviRawAudioStream is not null)
853855
{
854856
FlushBufferedAudio();
855857
}
856858

857-
if (_pAviCompressedVideoStream != IntPtr.Zero)
859+
if (_pAviCompressedVideoStream is not null)
858860
{
859861
_ = AVIWriterImports.AVIStreamRelease(_pAviCompressedVideoStream);
860-
_pAviCompressedVideoStream = IntPtr.Zero;
862+
_pAviCompressedVideoStream = null;
861863
}
862864
}
863865

@@ -885,7 +887,7 @@ public void AddSamples(IReadOnlyList<short> samples)
885887
}
886888
}
887889

888-
private unsafe void FlushBufferedAudio()
890+
private void FlushBufferedAudio()
889891
{
890892
var todo = _outStatus.audio_buffered_shorts;
891893
var todo_realsamples = todo / 2;
@@ -898,22 +900,23 @@ private unsafe void FlushBufferedAudio()
898900
}
899901

900902
// (TODO - inefficient- build directly in a buffer)
903+
int bytesWritten;
901904
_ = AVIWriterImports.AVIStreamWrite(
902905
_pAviRawAudioStream,
903906
_outStatus.audio_samples,
904907
todo_realsamples,
905-
buf,
908+
buf.ToPointer(),
906909
todo_realsamples * 4,
907910
0,
908-
IntPtr.Zero,
909-
out var bytes_written);
911+
null,
912+
&bytesWritten);
910913
_outStatus.audio_samples += todo_realsamples;
911-
_outStatus.audio_bytes += bytes_written;
914+
_outStatus.audio_bytes += bytesWritten;
912915
_outStatus.audio_buffered_shorts = 0;
913916
}
914917

915918
/// <exception cref="InvalidOperationException">attempted frame resize during encoding</exception>
916-
public unsafe void AddFrame(IVideoProvider source)
919+
public void AddFrame(IVideoProvider source)
917920
{
918921
if (_parameters.width != source.BufferWidth
919922
|| _parameters.height != source.BufferHeight)
@@ -953,17 +956,17 @@ public unsafe void AddFrame(IVideoProvider source)
953956
bp += pitch_add;
954957
}
955958

956-
int bytes_written = default;
959+
int bytesWritten;
957960
_ = AVIWriterImports.AVIStreamWrite(
958961
_pAviCompressedVideoStream,
959962
lStart: _outStatus.video_frames,
960-
samples: 1,
963+
lSamples: 1,
961964
lpBuffer: bytes_ptr,
962965
cbBuffer: todo,
963966
dwFlags: AVIWriterImports.AVIIF_KEYFRAME,
964-
plSampWritten: default,
965-
plBytesWritten: &bytes_written);
966-
_outStatus.video_bytes += bytes_written;
967+
plSampWritten: null,
968+
plBytesWritten: &bytesWritten);
969+
_outStatus.video_bytes += bytesWritten;
967970
_outStatus.video_frames++;
968971
}
969972
}
@@ -994,16 +997,17 @@ public unsafe void AddFrame(IVideoProvider source)
994997
idx -= w * 2;
995998
}
996999

1000+
int bytesWritten;
9971001
_ = AVIWriterImports.AVIStreamWrite(
9981002
_pAviCompressedVideoStream,
9991003
lStart: _outStatus.video_frames,
1000-
samples: 1,
1004+
lSamples: 1,
10011005
lpBuffer: bytes_ptr,
10021006
cbBuffer: todo * 3,
10031007
dwFlags: AVIWriterImports.AVIIF_KEYFRAME,
1004-
plSampWritten: default,
1005-
plBytesWritten: &bytes_written);
1006-
_outStatus.video_bytes += bytes_written;
1008+
plSampWritten: null,
1009+
plBytesWritten: &bytesWritten);
1010+
_outStatus.video_bytes += bytesWritten;
10071011
_outStatus.video_frames++;
10081012
}
10091013
}

0 commit comments

Comments
 (0)