Changed Qt Avi recording to use atomic buffer indices to ensure both threads are aware of changes when they happen.

This commit is contained in:
harry 2024-05-11 07:09:42 -04:00
parent 283aea91db
commit ffb28e1131
1 changed files with 62 additions and 39 deletions

View File

@ -26,6 +26,7 @@
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include <string> #include <string>
#include <atomic>
#ifdef WIN32 #ifdef WIN32
#include <windows.h> #include <windows.h>
@ -79,12 +80,12 @@ extern "C"
static gwavi_t *gwavi = NULL; static gwavi_t *gwavi = NULL;
static bool recordEnable = false; static bool recordEnable = false;
static bool recordAudio = true; static bool recordAudio = true;
static int vbufHead = 0; static std::atomic<int> vbufHead = 0;
static int vbufTail = 0; static std::atomic<int> vbufTail = 0;
static int vbufSize = 0; static constexpr int vbufSize = 1024 * 1024 * 64;
static int abufHead = 0; static std::atomic<int> abufHead = 0;
static int abufTail = 0; static std::atomic<int> abufTail = 0;
static int abufSize = 0; static constexpr int abufSize = 256 * 1024;
static uint32_t *rawVideoBuf = NULL; static uint32_t *rawVideoBuf = NULL;
static int16_t *rawAudioBuf = NULL; static int16_t *rawAudioBuf = NULL;
static int aviDriver = 0; static int aviDriver = 0;
@ -2326,10 +2327,8 @@ int aviRecordOpenFile( const char *filepath )
} }
} }
vbufSize = 1024 * 1024 * 60;
rawVideoBuf = (uint32_t*)malloc( vbufSize * sizeof(uint32_t) ); rawVideoBuf = (uint32_t*)malloc( vbufSize * sizeof(uint32_t) );
abufSize = 96000;
rawAudioBuf = (int16_t*)malloc( abufSize * sizeof(uint16_t) ); rawAudioBuf = (int16_t*)malloc( abufSize * sizeof(uint16_t) );
vbufHead = 0; vbufHead = 0;
@ -2348,10 +2347,6 @@ int aviRecordAddFrame( void )
return -1; return -1;
} }
//if ( gwavi == NULL )
//{
// return -1;
//}
if ( FCEUI_EmulationPaused() ) if ( FCEUI_EmulationPaused() )
{ {
return 0; return 0;
@ -2361,25 +2356,28 @@ int aviRecordAddFrame( void )
numPixels = nes_shm->video.ncol * nes_shm->video.nrow; numPixels = nes_shm->video.ncol * nes_shm->video.nrow;
availSize = (vbufTail - vbufHead); head = vbufHead;
if ( availSize <= 0 )
auto calcAvailSize = [&]()
{ {
availSize += vbufSize; availSize = (vbufTail - head);
} if ( availSize <= 0 )
{
availSize += vbufSize;
}
};
calcAvailSize();
while ( numPixels > availSize ) while ( numPixels > availSize )
{ {
//printf("Video Unavail %i \n", availSize ); //printf("Video Unavail %i \n", availSize );
msleep(1); msleep(1);
availSize = (vbufTail - vbufHead); calcAvailSize();
if ( availSize <= 0 )
{
availSize += vbufSize;
}
} }
i = 0; head = vbufHead; i = 0;
while ( i < numPixels ) while ( i < numPixels )
{ {
@ -2408,12 +2406,17 @@ int aviRecordAddAudioFrame( int32_t *buf, int numSamples )
return -1; return -1;
} }
// Get current buffer index values from atomic variables and store in stack variables
// Do loop processing with stack variables and then update atomics when finished
int head = abufHead;
for (int i=0; i<numSamples; i++) for (int i=0; i<numSamples; i++)
{ {
rawAudioBuf[ abufHead ] = buf[i]; rawAudioBuf[ head ] = buf[i];
abufHead = (abufHead + 1) % abufSize; head = (head + 1) % abufSize;
} }
abufHead = head;
return 0; return 0;
} }
@ -2437,8 +2440,10 @@ int aviRecordClose(void)
{ {
free(rawAudioBuf); rawAudioBuf = NULL; free(rawAudioBuf); rawAudioBuf = NULL;
} }
vbufTail = abufTail = 0; vbufHead = 0;
vbufSize = abufSize = 0; abufHead = 0;
vbufTail = 0;
abufTail = 0;
return 0; return 0;
} }
@ -2600,6 +2605,8 @@ void AviRecordDiskThread_t::run(void)
char localRecordAudio = 0; char localRecordAudio = 0;
int avgAudioPerFrame, audioChunkSize, audioSamplesAvail=0; int avgAudioPerFrame, audioChunkSize, audioSamplesAvail=0;
int localVideoFormat; int localVideoFormat;
int audioHead = 0;
int audioTail = 0;
fprintf( avLogFp, "AVI Record Disk Thread Start\n"); fprintf( avLogFp, "AVI Record Disk Thread Start\n");
@ -2672,12 +2679,19 @@ void AviRecordDiskThread_t::run(void)
// Main Disk Record Loop // Main Disk Record Loop
while ( !isInterruptionRequested() ) while ( !isInterruptionRequested() )
{ {
while ( (numPixelsReady < numPixels) && (vbufTail != vbufHead) )
{ {
videoOut[ numPixelsReady ] = rawVideoBuf[ vbufTail ]; numPixelsReady++; // Get current buffer index values from atomic variables and store in stack variables
// Do loop processing with stack variables and then update atomics when finished
int vhead = vbufHead;
int vtail = vbufTail;
vbufTail = (vbufTail + 1) % vbufSize; while ( (numPixelsReady < numPixels) && (vtail != vhead) )
{
videoOut[ numPixelsReady ] = rawVideoBuf[ vtail ]; numPixelsReady++;
vtail = (vtail + 1) % vbufSize;
}
vbufTail = vtail;
} }
if ( numPixelsReady >= numPixels ) if ( numPixelsReady >= numPixels )
@ -2731,7 +2745,11 @@ void AviRecordDiskThread_t::run(void)
numPixelsReady = 0; numPixelsReady = 0;
audioSamplesAvail = abufHead - abufTail; // Get current buffer index values from atomic variables and store in stack variables
// Do loop processing with stack variables and then update atomics when finished
audioHead = abufHead;
audioTail = abufTail;
audioSamplesAvail = audioHead - audioTail;
if ( audioSamplesAvail < 0 ) if ( audioSamplesAvail < 0 )
{ {
@ -2743,17 +2761,18 @@ void AviRecordDiskThread_t::run(void)
{ {
numSamples = 0; numSamples = 0;
while ( abufHead != abufTail ) while ( audioHead != audioTail )
{ {
audioOut[ numSamples ] = rawAudioBuf[ abufTail ]; numSamples++; audioOut[ numSamples ] = rawAudioBuf[ audioTail ]; numSamples++;
abufTail = (abufTail + 1) % abufSize; audioTail = (audioTail + 1) % abufSize;
if ( numSamples >= audioChunkSize ) if ( numSamples >= audioChunkSize )
{ {
break; break;
} }
} }
abufTail = audioTail;
if ( numSamples > 0 ) if ( numSamples > 0 )
{ {
@ -2779,8 +2798,11 @@ void AviRecordDiskThread_t::run(void)
} }
} }
audioHead = abufHead;
audioTail = abufTail;
// Write Leftover Audio Samples // Write Leftover Audio Samples
audioSamplesAvail = abufHead - abufTail; audioSamplesAvail = audioHead - audioTail;
if ( audioSamplesAvail < 0 ) if ( audioSamplesAvail < 0 )
{ {
@ -2793,12 +2815,13 @@ void AviRecordDiskThread_t::run(void)
//printf("Writing Last %i Audio Samples\n", audioSamplesAvail ); //printf("Writing Last %i Audio Samples\n", audioSamplesAvail );
numSamples = 0; numSamples = 0;
while ( abufHead != abufTail ) while ( audioHead != audioTail )
{ {
audioOut[ numSamples ] = rawAudioBuf[ abufTail ]; numSamples++; audioOut[ numSamples ] = rawAudioBuf[ audioTail ]; numSamples++;
abufTail = (abufTail + 1) % abufSize; audioTail = (audioTail + 1) % abufSize;
} }
abufTail = audioTail;
if ( numSamples > 0 ) if ( numSamples > 0 )
{ {