Windows Port: Do a complete code cleanup and refactor of aviout.cpp to use proper C++ objects.
- aviout.cpp now uses Windows-style line-endings instead of Unix-style line-endings. - AVI segments now fill up much closer to the 2 GB file limit than before. - Error handling in the file writing thread is much more robust.
This commit is contained in:
parent
cbe4717d2f
commit
db1a19ad86
File diff suppressed because it is too large
Load Diff
|
@ -18,16 +18,134 @@
|
|||
#ifndef _AVIOUT_H_
|
||||
#define _AVIOUT_H_
|
||||
|
||||
#include "types.h"
|
||||
#include <windows.h>
|
||||
#include <vfw.h>
|
||||
|
||||
bool DRV_AviBegin(const char* fname, bool newsegment = false);
|
||||
void DRV_AviEnd(bool newsegment = false);
|
||||
#include "GPU.h"
|
||||
#include "SPU.h"
|
||||
#include "utils/task.h"
|
||||
|
||||
#define VIDEO_STREAM 0
|
||||
#define AUDIO_STREAM 1
|
||||
#define MAX_CONVERT_THREADS 32
|
||||
|
||||
#define AUDIO_STREAM_BUFFER_SIZE ((DESMUME_SAMPLE_RATE * sizeof(u16) * 2) / 30) // 16-bit samples, 2 channels, 2 frames (need only 1 frame's worth, but have 2 frame's worth for safety)
|
||||
#define MAX_AVI_FILE_SIZE (2ULL * 1024ULL * 1024ULL * 1024ULL) // Max file size should be 2 GB due to the Video for Windows AVI limit.
|
||||
#define PENDING_BUFFER_COUNT 2 // Number of pending buffers to maintain for file writes. Each pending buffer will store 1 frame's worth of the audio/video streams.
|
||||
|
||||
class NDSCaptureObject;
|
||||
class AVIFileStream;
|
||||
|
||||
struct VideoConvertParam
|
||||
{
|
||||
NDSCaptureObject *captureObj;
|
||||
|
||||
const void *src;
|
||||
u8 *dst;
|
||||
|
||||
size_t srcOffset;
|
||||
size_t dstOffset;
|
||||
|
||||
size_t firstLineIndex;
|
||||
size_t lastLineIndex;
|
||||
size_t frameWidth;
|
||||
};
|
||||
typedef struct VideoConvertParam VideoConvertParam;
|
||||
|
||||
struct AVIFileWriteParam
|
||||
{
|
||||
AVIFileStream *fs;
|
||||
u8 *srcVideo;
|
||||
u8 *srcAudio;
|
||||
size_t videoBufferSize;
|
||||
size_t audioBufferSize;
|
||||
};
|
||||
typedef struct AVIFileWriteParam AVIFileWriteParam;
|
||||
|
||||
class AVIFileStream
|
||||
{
|
||||
private:
|
||||
static bool __needAviLibraryInit;
|
||||
|
||||
protected:
|
||||
PAVIFILE _file;
|
||||
PAVISTREAM _stream[2];
|
||||
PAVISTREAM _compressedStream[2];
|
||||
AVISTREAMINFO _streamInfo[2];
|
||||
|
||||
AVICOMPRESSOPTIONS _compressionOptions[2];
|
||||
BITMAPINFOHEADER _bmpFormat;
|
||||
WAVEFORMATEX _wavFormat;
|
||||
|
||||
char _baseFileName[MAX_PATH];
|
||||
char _baseFileNameExt[MAX_PATH];
|
||||
size_t _segmentNumber;
|
||||
|
||||
size_t _expectedFrameSize;
|
||||
size_t _writtenBytes;
|
||||
LONG _writtenVideoFrameCount;
|
||||
LONG _writtenAudioSampleCount;
|
||||
|
||||
public:
|
||||
AVIFileStream();
|
||||
~AVIFileStream();
|
||||
|
||||
HRESULT Open(const char *fileName, BITMAPINFOHEADER *bmpFormat, WAVEFORMATEX *wavFormat);
|
||||
void Close();
|
||||
bool IsValid();
|
||||
|
||||
HRESULT FlushVideo(u8 *srcBuffer, const LONG bufferSize);
|
||||
HRESULT FlushAudio(u8 *srcBuffer, const LONG bufferSize);
|
||||
HRESULT WriteOneFrame(u8 *srcVideo, const LONG videoBufferSize, u8 *srcAudio, const LONG audioBufferSize);
|
||||
};
|
||||
|
||||
class NDSCaptureObject
|
||||
{
|
||||
protected:
|
||||
AVIFileStream *_fs;
|
||||
|
||||
BITMAPINFOHEADER _bmpFormat;
|
||||
WAVEFORMATEX _wavFormat;
|
||||
|
||||
u8 *_pendingVideoBuffer;
|
||||
u8 _pendingAudioBuffer[AUDIO_STREAM_BUFFER_SIZE * PENDING_BUFFER_COUNT];
|
||||
size_t _pendingAudioWriteSize[2];
|
||||
size_t _currentBufferIndex;
|
||||
|
||||
size_t _numThreads;
|
||||
Task *_fileWriteThread;
|
||||
Task *_convertThread[MAX_CONVERT_THREADS];
|
||||
VideoConvertParam _convertParam[MAX_CONVERT_THREADS];
|
||||
AVIFileWriteParam _fileWriteParam;
|
||||
|
||||
public:
|
||||
NDSCaptureObject();
|
||||
NDSCaptureObject(size_t videoWidth, size_t videoHeight, const WAVEFORMATEX *wfex);
|
||||
~NDSCaptureObject();
|
||||
|
||||
HRESULT OpenFileStream(const char *fileName);
|
||||
void CloseFileStream();
|
||||
bool IsFileStreamValid();
|
||||
|
||||
void StartFrame();
|
||||
void StreamWriteStart();
|
||||
void StreamWriteFinish();
|
||||
|
||||
void ConvertVideoSlice555Xto888(const VideoConvertParam ¶m);
|
||||
void ConvertVideoSlice888Xto888(const VideoConvertParam ¶m);
|
||||
|
||||
void ReadVideoFrame(const void *srcVideoFrame, const size_t inFrameWidth, const size_t inFrameHeight, const NDSColorFormat colorFormat);
|
||||
void ReadAudioFrames(const void *srcAudioBuffer, const size_t inSampleCount);
|
||||
};
|
||||
|
||||
bool DRV_AviBegin(const char *fileName);
|
||||
void DRV_AviEnd();
|
||||
bool AVI_IsRecording();
|
||||
|
||||
void DRV_AviFrameStart();
|
||||
void DRV_AviVideoUpdate();
|
||||
void DRV_AviSoundUpdate(void* soundData, int soundLen);
|
||||
void DRV_AviFileWrite();
|
||||
void DRV_AviVideoUpdate(const NDSDisplayInfo &displayInfo);
|
||||
void DRV_AviSoundUpdate(void *soundData, const int soundLen);
|
||||
void DRV_AviFileWriteStart();
|
||||
void DRV_AviFileWriteFinish();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -548,7 +548,7 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
DRV_AviVideoUpdate();
|
||||
DRV_AviVideoUpdate(latestDisplayInfo);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2235,7 +2235,7 @@ static void StepRunLoop_Core()
|
|||
}
|
||||
inFrameBoundary = true;
|
||||
|
||||
DRV_AviFileWrite();
|
||||
DRV_AviFileWriteStart();
|
||||
|
||||
CallRegisteredLuaFunctions(LUACALL_AFTEREMULATION);
|
||||
ServiceDisplayThreadInvocations();
|
||||
|
@ -3515,7 +3515,6 @@ int _main()
|
|||
|
||||
KillDisplay();
|
||||
|
||||
DRV_AviFileWriteFinish();
|
||||
DRV_AviEnd();
|
||||
WAV_End();
|
||||
|
||||
|
@ -3807,8 +3806,11 @@ void SetRotate(HWND hwnd, int rot, bool user)
|
|||
void AviEnd()
|
||||
{
|
||||
NDS_Pause();
|
||||
DRV_AviFileWriteFinish();
|
||||
|
||||
DRV_AviEnd();
|
||||
LOG("AVI recording ended.");
|
||||
driver->AddLine("AVI recording ended.");
|
||||
|
||||
NDS_UnPause();
|
||||
}
|
||||
|
||||
|
@ -3868,9 +3870,21 @@ void AviRecordTo()
|
|||
ofn.nMaxFile = MAX_PATH;
|
||||
ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOREADONLYRETURN | OFN_PATHMUSTEXIST;
|
||||
|
||||
if(GetSaveFileName(&ofn))
|
||||
if (GetSaveFileName(&ofn))
|
||||
{
|
||||
DRV_AviBegin(folder);
|
||||
if (AVI_IsRecording())
|
||||
{
|
||||
DRV_AviEnd();
|
||||
LOG("AVI recording ended.");
|
||||
driver->AddLine("AVI recording ended.");
|
||||
}
|
||||
|
||||
bool result = DRV_AviBegin(folder);
|
||||
if (result)
|
||||
{
|
||||
LOG("AVI recording started.");
|
||||
driver->AddLine("AVI recording started.");
|
||||
}
|
||||
}
|
||||
|
||||
NDS_UnPause();
|
||||
|
|
Loading…
Reference in New Issue